From 5b6e5a75099f997cda5a8f5cbaeaa74140ebf4d7 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 19 Jun 2022 21:24:54 +0100 Subject: [PATCH 001/113] [Temp] New input pane --- .../Telegram-iOS/en.lproj/Localizable.strings | 24 +- .../Sources/AccountContext.swift | 2 +- .../Sources/OpenChatMessage.swift | 4 +- .../Source/ASTextKitComponents.mm | 4 +- .../Sources/AttachmentPanel.swift | 2 + .../ChatPanelInterfaceInteraction.swift | 17 +- .../Source/Base/Transition.swift | 23 +- .../BlurredBackgroundComponent/BUILD | 20 + .../Sources/BlurredBackgroundComponent.swift | 39 ++ .../Sources/BundleIconComponent.swift | 12 +- .../Components/ComponentDisplayAdapters/BUILD | 19 + .../Sources/ComponentDisplayAdapters.swift | 50 ++ .../PagerComponent}/BUILD | 5 +- .../Sources/PagerComponent.swift | 524 +++++++++++++++ .../Components/ViewControllerComponent/BUILD | 1 + .../Sources/ViewControllerComponent.swift | 47 +- submodules/Display/Source/DeviceMetrics.swift | 38 +- submodules/Display/Source/NavigationBar.swift | 162 ++++- .../JoinLinkPreviewControllerNode.swift | 2 +- .../LanguageLinkPreviewControllerNode.swift | 2 +- .../PasscodeUI/Sources/PasscodeLayout.swift | 8 +- submodules/Postbox/Sources/MediaBox.swift | 3 +- .../StickerPackPreviewController.swift | 6 +- .../StickerPackPreviewControllerNode.swift | 6 +- .../Sources/StickerPackScreen.swift | 18 +- .../Sources/VoiceChatJoinScreen.swift | 2 +- submodules/TelegramUI/BUILD | 3 +- .../Sources/AnimationCache.swift | 46 +- .../EmojiKeyboard/Sources/EmojiKeyboard.swift | 4 - .../Sources/EmojiTextAttachmentView.swift | 12 +- .../Components/EntityKeyboard/BUILD | 35 + .../Sources/EmojiPagerContentComponent.swift | 631 ++++++++++++++++++ .../Sources/EntityKeyboard.swift | 214 ++++++ .../EntityKeyboardBottomPanelComponent.swift | 293 ++++++++ ...tyKeyboardTopContainerPanelComponent.swift | 136 ++++ .../EntityKeyboardTopPanelComponent.swift | 315 +++++++++ .../Sources/MultiAnimationRenderer.swift | 68 +- .../Contents.json | 12 + .../ic_clear.pdf | 107 +++ .../Contents.json | 12 + .../ic_emoji.pdf | 123 ++++ .../Contents.json | 12 + .../EntityInputGifsIcon.imageset/ic_gifs.pdf | 128 ++++ .../Contents.json | 12 + .../ic_search.pdf | 82 +++ .../Contents.json | 12 + .../ic_tools.pdf | 177 +++++ .../Contents.json | 12 + .../ic_stickers.pdf | 431 ++++++++++++ .../TelegramUI/Sources/ChatController.swift | 106 +-- .../Sources/ChatControllerInteraction.swift | 4 +- .../Sources/ChatControllerNode.swift | 194 +++++- .../TelegramUI/Sources/ChatEmptyNode.swift | 4 +- .../Sources/ChatEntityKeyboardInputNode.swift | 217 ++++++ .../TelegramUI/Sources/ChatInputNode.swift | 5 + .../Sources/ChatInterfaceInputContexts.swift | 8 +- .../Sources/ChatInterfaceInputNodes.swift | 43 +- .../Sources/ChatMediaInputNode.swift | 16 +- .../ChatMediaInputStickerGridItem.swift | 2 +- .../Sources/ChatRecentActionsController.swift | 2 + .../Sources/ChatTextInputPanelNode.swift | 93 ++- .../Sources/DrawingStickersScreen.swift | 14 +- .../Sources/FeaturedStickersScreen.swift | 24 +- ...textResultsChatInputContextPanelNode.swift | 4 +- .../Sources/HorizontalStickerGridItem.swift | 8 +- ...rizontalStickersChatContextPanelNode.swift | 2 +- .../Sources/InlineReactionSearchPanel.swift | 14 +- .../LegacyInstantVideoController.swift | 4 +- .../TelegramUI/Sources/OpenResolvedUrl.swift | 2 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 10 +- .../Sources/PeerSelectionControllerNode.swift | 2 + .../Sources/SharedAccountContext.swift | 2 +- .../StickerPaneSearchContentNode.swift | 10 +- .../StickersChatInputContextPanelItem.swift | 2 +- .../StickersChatInputContextPanelNode.swift | 2 +- 75 files changed, 4378 insertions(+), 333 deletions(-) create mode 100644 submodules/Components/BlurredBackgroundComponent/BUILD create mode 100644 submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift create mode 100644 submodules/Components/ComponentDisplayAdapters/BUILD create mode 100644 submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift rename submodules/{TelegramUI/Components/EmojiKeyboard => Components/PagerComponent}/BUILD (72%) create mode 100644 submodules/Components/PagerComponent/Sources/PagerComponent.swift delete mode 100644 submodules/TelegramUI/Components/EmojiKeyboard/Sources/EmojiKeyboard.swift create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/BUILD create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/ic_clear.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/ic_emoji.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/ic_gifs.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/ic_search.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/ic_stickers.pdf create mode 100644 submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 723ca92073..6145e30744 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7543,7 +7543,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"; @@ -7592,9 +7592,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."; @@ -7604,7 +7604,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."; @@ -7635,10 +7635,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**."; @@ -7647,7 +7647,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."; @@ -7666,10 +7666,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"; @@ -7677,7 +7677,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"; @@ -7708,7 +7708,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."; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index a8cc36c4a2..f19aa57c43 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -724,7 +724,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) 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/AsyncDisplayKit/Source/ASTextKitComponents.mm b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm index c73adc2330..7bf26bcf8b 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; } diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 80203f71c7..011a9cb6af 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -691,6 +691,8 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, displayCopyProtectionTip: { _, _ in }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index 5b2d46fcbb..13e206aff6 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -98,7 +98,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) -> Bool public let unblockPeer: () -> Void public let pinMessage: (MessageId, ContextControllerProtocol?) -> Void public let unpinMessage: (MessageId, Bool, ContextControllerProtocol?) -> Void @@ -123,7 +123,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 +144,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: (String) -> Void + public let backwardsDeleteText: () -> Void public let chatController: () -> ViewController? public let statuses: ChatPanelInterfaceInteractionStatuses? @@ -192,7 +194,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) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId, ContextControllerProtocol?) -> Void, unpinMessage: @escaping (MessageId, Bool, ContextControllerProtocol?) -> Void, @@ -217,7 +219,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 +240,8 @@ public final class ChatPanelInterfaceInteraction { displayCopyProtectionTip: @escaping (ASDisplayNode, Bool) -> Void, openWebView: @escaping (String, String, Bool, Bool) -> Void, updateShowWebView: @escaping ((Bool) -> Bool) -> Void, + insertText: @escaping (String) -> Void, + backwardsDeleteText: @escaping () -> Void, chatController: @escaping () -> ViewController?, statuses: ChatPanelInterfaceInteractionStatuses? ) { @@ -331,6 +335,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 } @@ -431,6 +438,8 @@ public final class ChatPanelInterfaceInteraction { }, displayCopyProtectionTip: { _, _ in }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index dc8a1a4308..1477eb4fbd 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 } } @@ -182,10 +190,12 @@ public struct Transition { switch self.animation { case .none: view.frame = frame + view.layer.removeAnimation(forKey: "position") + view.layer.removeAnimation(forKey: "bounds") completion?(true) case .curve: - let previousPosition = view.center - let previousBounds = view.bounds + let previousPosition = view.layer.presentation()?.position ?? view.center + let previousBounds = view.layer.presentation()?.bounds ?? view.bounds view.frame = frame self.animatePosition(view: view, from: previousPosition, to: view.center, completion: completion) @@ -201,9 +211,10 @@ 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 = view.layer.presentation()?.bounds ?? view.bounds view.bounds = bounds self.animateBounds(view: view, from: previousBounds, to: view.bounds, completion: completion) @@ -218,9 +229,10 @@ 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 = view.layer.presentation()?.position ?? view.center view.center = position self.animatePosition(view: view, from: previousPosition, to: view.center, completion: completion) @@ -235,9 +247,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) } 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..0717467711 --- /dev/null +++ b/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift @@ -0,0 +1,39 @@ +import Foundation +import UIKit +import ComponentFlow +import Display +import ComponentDisplayAdapters + +public final class BlurredBackgroundComponent: Component { + public let color: UIColor + + public init( + color: UIColor + ) { + self.color = color + } + + public static func ==(lhs: BlurredBackgroundComponent, rhs: BlurredBackgroundComponent) -> Bool { + if lhs.color != rhs.color { + return false + } + return true + } + + public final class View: BlurredBackgroundView { + public func update(component: BlurredBackgroundComponent, availableSize: CGSize, transition: Transition) -> CGSize { + self.updateColor(color: component.color, transition: transition.containedViewLayoutTransition) + self.update(size: availableSize, transition: transition.containedViewLayoutTransition) + + return availableSize + } + } + + public func makeView() -> View { + return View(color: .clear, 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..34fa9ce017 --- /dev/null +++ b/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift @@ -0,0 +1,50 @@ +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 .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) + } + } +} \ No newline at end of file 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..daa4be7312 --- /dev/null +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -0,0 +1,524 @@ +import Foundation +import UIKit +import Display +import ComponentFlow + +public final class PagerComponentChildEnvironment: Equatable { + public struct ContentScrollingUpdate { + public var relativeOffset: CGFloat + public var absoluteOffsetToClosestEdge: CGFloat? + public var transition: Transition + + public init( + relativeOffset: CGFloat, + absoluteOffsetToClosestEdge: CGFloat?, + transition: Transition + ) { + self.relativeOffset = relativeOffset + self.absoluteOffsetToClosestEdge = absoluteOffsetToClosestEdge + 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: [AnyComponentWithIdentity] + public let contentAccessoryRightButtons: [AnyComponentWithIdentity] + public let activeContentId: AnyHashable? + + init( + contentOffset: CGFloat, + contentTopPanels: [AnyComponentWithIdentity], + contentIcons: [AnyComponentWithIdentity], + contentAccessoryRightButtons: [AnyComponentWithIdentity], + activeContentId: AnyHashable? + ) { + self.contentOffset = contentOffset + self.contentTopPanels = contentTopPanels + self.contentIcons = contentIcons + self.contentAccessoryRightButtons = contentAccessoryRightButtons + self.activeContentId = activeContentId + } + + 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.contentAccessoryRightButtons != rhs.contentAccessoryRightButtons { + return false + } + if lhs.activeContentId != rhs.activeContentId { + return false + } + + return true + } +} + +public struct PagerComponentPanelState { + public var topPanelHeight: CGFloat + + public init(topPanelHeight: CGFloat) { + self.topPanelHeight = topPanelHeight + } +} + +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: [AnyComponentWithIdentity] + public let contentAccessoryRightButtons:[AnyComponentWithIdentity] + public let defaultId: AnyHashable? + public let contentBackground: AnyComponent? + public let topPanel: AnyComponent? + public let externalTopPanelContainer: UIView? + public let bottomPanel: AnyComponent? + public let panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)? + + public init( + contentInsets: UIEdgeInsets, + contents: [AnyComponentWithIdentity<(ChildEnvironmentType, PagerComponentChildEnvironment)>], + contentTopPanels: [AnyComponentWithIdentity], + contentIcons: [AnyComponentWithIdentity], + contentAccessoryRightButtons:[AnyComponentWithIdentity], + defaultId: AnyHashable?, + contentBackground: AnyComponent?, + topPanel: AnyComponent?, + externalTopPanelContainer: UIView?, + bottomPanel: AnyComponent?, + panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)? + ) { + self.contentInsets = contentInsets + self.contents = contents + self.contentTopPanels = contentTopPanels + self.contentIcons = contentIcons + self.contentAccessoryRightButtons = contentAccessoryRightButtons + self.defaultId = defaultId + self.contentBackground = contentBackground + self.topPanel = topPanel + self.externalTopPanelContainer = externalTopPanelContainer + self.bottomPanel = bottomPanel + self.panelStateUpdated = panelStateUpdated + } + + 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 + } + + return true + } + + public final class View: UIView { + private final class ContentView { + let view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)> + var scrollingPanelOffsetToClosestEdge: CGFloat = 0.0 + + init(view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)>) { + self.view = view + } + } + + private struct PaneTransitionGestureState { + var fraction: CGFloat = 0.0 + } + + private var contentViews: [AnyHashable: ContentView] = [:] + private var contentBackgroundView: ComponentHostView? + private var topPanelView: ComponentHostView? + private var bottomPanelView: ComponentHostView? + + private var centralId: AnyHashable? + private var paneTransitionGestureState: PaneTransitionGestureState? + + private var component: PagerComponent? + private weak var state: EmptyComponentState? + + private var panRecognizer: UIPanGestureRecognizer? + + override init(frame: CGRect) { + super.init(frame: frame) + + self.disablesInteractiveTransitionGestureRecognizer = true + + let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) + self.panRecognizer = panRecognizer + self.addGestureRecognizer(panRecognizer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + @objc private func panGesture(_ recognizer: UIPanGestureRecognizer) { + switch recognizer.state { + case .began: + self.paneTransitionGestureState = PaneTransitionGestureState() + case .changed: + if var paneTransitionGestureState = self.paneTransitionGestureState, self.bounds.width > 0.0 { + paneTransitionGestureState.fraction = recognizer.translation(in: self).x / self.bounds.width + + self.paneTransitionGestureState = paneTransitionGestureState + self.state?.updated(transition: .immediate) + } + case .ended, .cancelled: + if let paneTransitionGestureState = self.paneTransitionGestureState { + self.paneTransitionGestureState = nil + + 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 + } + } + + 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 { + self.component = component + self.state = state + + 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 + } + } else { + centralId = component.contents.first?.id + } + } + + if self.centralId != centralId { + self.centralId = centralId + } + + var contentInsets = component.contentInsets + + let scrollingPanelOffsetToClosestEdge: CGFloat + if let centralId = centralId, let centralContentView = self.contentViews[centralId] { + scrollingPanelOffsetToClosestEdge = centralContentView.scrollingPanelOffsetToClosestEdge + } else { + scrollingPanelOffsetToClosestEdge = 0.0 + } + + var topPanelHeight: CGFloat = 0.0 + if let topPanel = component.topPanel { + let topPanelView: ComponentHostView + var topPanelTransition = transition + if let current = self.topPanelView { + topPanelView = current + } else { + topPanelTransition = .immediate + topPanelView = ComponentHostView() + topPanelView.clipsToBounds = true + 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: [], + contentAccessoryRightButtons: [], + activeContentId: centralId + ) + }, + containerSize: availableSize + ) + + let topPanelOffset = max(0.0, min(topPanelSize.height, scrollingPanelOffsetToClosestEdge)) + + topPanelHeight = max(0.0, topPanelSize.height - topPanelOffset) + + if component.externalTopPanelContainer != nil { + let visibleTopPanelHeight = max(0.0, topPanelSize.height - topPanelOffset) + transition.setFrame(view: topPanelView, frame: CGRect(origin: CGPoint(), size: CGSize(width: topPanelSize.width, height: visibleTopPanelHeight))) + } else { + transition.setFrame(view: topPanelView, frame: CGRect(origin: CGPoint(x: 0.0, y: -topPanelOffset), size: topPanelSize)) + } + + contentInsets.top += topPanelSize.height + } else { + if let bottomPanelView = self.bottomPanelView { + self.bottomPanelView = nil + + bottomPanelView.removeFromSuperview() + } + } + + var bottomPanelOffset: CGFloat = 0.0 + if let bottomPanel = component.bottomPanel { + let bottomPanelView: ComponentHostView + var bottomPanelTransition = transition + 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, + contentAccessoryRightButtons: component.contentAccessoryRightButtons, + activeContentId: centralId + ) + }, + containerSize: availableSize + ) + + bottomPanelOffset = max(0.0, min(bottomPanelSize.height, scrollingPanelOffsetToClosestEdge)) + + transition.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() + } + } + + if let contentBackground = component.contentBackground { + let contentBackgroundView: ComponentHostView + var contentBackgroundTransition = transition + if let current = self.contentBackgroundView { + contentBackgroundView = current + } else { + contentBackgroundTransition = .immediate + contentBackgroundView = ComponentHostView() + self.contentBackgroundView = contentBackgroundView + self.insertSubview(contentBackgroundView, at: 0) + } + let contentBackgroundSize = contentBackgroundView.update( + transition: contentBackgroundTransition, + component: contentBackground, + environment: {}, + containerSize: CGSize(width: availableSize.width, height: availableSize.height - topPanelHeight - contentInsets.bottom + bottomPanelOffset) + ) + contentBackgroundTransition.setFrame(view: contentBackgroundView, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelHeight), size: contentBackgroundSize)) + } 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) + + for index in 0 ..< component.contents.count { + let indexOffset = index - centralIndex + var contentFrame = CGRect(origin: CGPoint(x: contentSize.width * CGFloat(indexOffset), y: 0.0), size: contentSize) + if let paneTransitionGestureState = self.paneTransitionGestureState { + contentFrame.origin.x += paneTransitionGestureState.fraction * availableSize.width + } + let content = component.contents[index] + + let isInBounds = CGRect(origin: CGPoint(), size: availableSize).intersects(contentFrame) + + 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 { + 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) + } + } + }) + } + } + } + } + + var removedIds: [AnyHashable] = [] + for (id, contentView) in self.contentViews { + if !validIds.contains(id) { + removedIds.append(id) + contentView.view.removeFromSuperview() + } + } + for id in removedIds { + self.contentViews.removeValue(forKey: id) + } + + if let panelStateUpdated = component.panelStateUpdated { + panelStateUpdated( + PagerComponentPanelState( + topPanelHeight: topPanelHeight + ), + transition + ) + } + + return availableSize + } + + private func onChildScrollingUpdate(id: AnyHashable, update: PagerComponentChildEnvironment.ContentScrollingUpdate) { + guard let contentView = self.contentViews[id] else { + return + } + + if let absoluteOffsetToClosestEdge = update.absoluteOffsetToClosestEdge { + contentView.scrollingPanelOffsetToClosestEdge = absoluteOffsetToClosestEdge + } else { + contentView.scrollingPanelOffsetToClosestEdge = 1000.0 + } + + state?.updated(transition: update.transition) + } + } + + 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 ec7dc58860..9a4a02fa12 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 { 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/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 99bfdc5ac8..1eae1fcc89 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 @@ -266,6 +286,146 @@ 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 = .clear + self.enableBlur = enableBlur + + self.backgroundView = UIView() + + super.init(frame: CGRect()) + + self.addSubview(self.backgroundView) + + self.updateColor(color: color, transition: .immediate) + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func updateBackgroundBlur(forceKeepBlur: Bool) { + if self.enableBlur && !sharedIsReduceTransparencyEnabled && ((self._color.alpha > .ulpOfOne && self._color.alpha < 0.95) || forceKeepBlur) { + if self.effectView == nil { + let effectView = UIVisualEffectView(effect: UIBlurEffect(style: .light)) + + 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 + 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.isEqual(color) && self.enableBlur == effectiveEnableBlur { + return + } + self._color = color + self.enableBlur = effectiveEnableBlur + + if sharedIsReduceTransparencyEnabled { + transition.updateBackgroundColor(layer: self.backgroundView.layer, color: self._color.withAlphaComponent(1.0)) + } else { + transition.updateBackgroundColor(layer: self.backgroundView.layer, color: self._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/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/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/Postbox/Sources/MediaBox.swift b/submodules/Postbox/Sources/MediaBox.swift index 341b196a8b..5a6a01015f 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" ]) 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..a317390966 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -73,7 +73,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() @@ -220,9 +220,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) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 04b7b114c5..7cb8c4b2b2 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -85,7 +85,7 @@ private final class StickerPackContainer: ASDisplayNode { 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 @@ -129,7 +129,7 @@ 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?) { + 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, UIView, CGRect) -> Bool)?, openMention: @escaping (String) -> Void, controller: StickerPackScreenImpl?) { self.index = index self.context = context self.controller = controller @@ -367,9 +367,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) @@ -964,7 +964,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 +986,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 @@ -1302,7 +1302,7 @@ 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 @@ -1320,7 +1320,7 @@ public final class StickerPackScreenImpl: ViewController { private var alreadyDidAppear: 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) { + 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 @@ -1482,7 +1482,7 @@ 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 { +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 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/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 22e7126343..371cc76040 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -282,10 +282,11 @@ 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/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", "//submodules/Media/ConvertOpusToAAC:ConvertOpusToAAC", "//submodules/Media/LocalAudioTranscription:LocalAudioTranscription", ] + select({ diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 819d57826a..3201000137 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -41,9 +41,19 @@ public protocol AnimationCacheItemWriter: AnyObject { 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 getSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? } private func md5Hash(_ string: String) -> String { @@ -278,7 +288,7 @@ private func loadItem(path: String) -> AnimationCacheItem? { 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 { @@ -301,13 +311,13 @@ 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 + "-\(Int(size.width))x\(Int(size.height))")) let itemDirectoryPath = "\(self.basePath)/\(sourceIdPath.directory)" let itemPath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)" if FileManager.default.fileExists(atPath: itemPath) { - completion(loadItem(path: itemPath)) + updateResult(AnimationCacheItemResult(item: loadItem(path: itemPath), isFinal: true)) return EmptyDisposable } @@ -323,7 +333,9 @@ 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() @@ -349,14 +361,14 @@ public final class AnimationCacheImpl: AnimationCache { } for f in itemContext.subscribers.copyItems() { - f(item) + f(AnimationCacheItemResult(item: item, isFinal: true)) } } }) else { return EmptyDisposable } - let fetchDisposable = fetch(writer) + let fetchDisposable = fetch(size, writer) itemContext.disposable.set(ActionDisposable { fetchDisposable.dispose() @@ -377,8 +389,8 @@ public final class AnimationCacheImpl: AnimationCache { } } - func getSynchronously(sourceId: String) -> AnimationCacheItem? { - let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId)) + func getSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? { + let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId + "-\(Int(size.width))x\(Int(size.height))")) let itemDirectoryPath = "\(self.basePath)/\(sourceIdPath.directory)" let itemPath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)" @@ -401,14 +413,16 @@ public final class AnimationCacheImpl: AnimationCache { }) } - 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 +431,9 @@ public final class AnimationCacheImpl: AnimationCache { |> runOn(self.queue) } - public func getSynchronously(sourceId: String) -> AnimationCacheItem? { + public func getSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? { return self.impl.syncWith { impl -> AnimationCacheItem? in - return impl.getSynchronously(sourceId: sourceId) + return impl.getSynchronously(sourceId: sourceId, size: size) } } } 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/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index 700adef954..051259f600 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -46,16 +46,19 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { super.init() + let scale = min(2.0, UIScreenScale) + let pixelSize = CGSize(width: 24 * scale, height: 24 * scale) + 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 !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { + let size = CGSize(width: pixelSize.width / scale, height: pixelSize.height / scale) 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 + self.disposable = renderer.add(groupId: groupId, target: self, 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 @@ -67,8 +70,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { writer.finish() return } - let scale = min(2.0, UIScreenScale) - cacheLottieAnimation(data: data, width: Int(24 * scale), height: Int(24 * scale), writer: writer) + cacheLottieAnimation(data: data, width: Int(size.width), height: Int(size.height), writer: writer) }) let fetchDisposable = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)).start() diff --git a/submodules/TelegramUI/Components/EntityKeyboard/BUILD b/submodules/TelegramUI/Components/EntityKeyboard/BUILD new file mode 100644 index 0000000000..254b799425 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/BUILD @@ -0,0 +1,35 @@ +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/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/ShimmerEffect:ShimmerEffect", + ], + 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..0c684fa098 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -0,0 +1,631 @@ +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 + +public final class EmojiPagerContentComponent: Component { + public typealias EnvironmentType = (EntityKeyboardChildEnvironment, PagerComponentChildEnvironment) + + public final class InputInteraction { + public let performItemAction: (Item, UIView, CGRect) -> Void + public let deleteBackwards: () -> Void + + public init( + performItemAction: @escaping (Item, UIView, CGRect) -> Void, + deleteBackwards: @escaping () -> Void + ) { + self.performItemAction = performItemAction + self.deleteBackwards = deleteBackwards + } + } + + public final class Item: Equatable { + public let emoji: String + public let file: TelegramMediaFile + + public init(emoji: String, file: TelegramMediaFile) { + self.emoji = emoji + self.file = file + } + + public static func ==(lhs: Item, rhs: Item) -> Bool { + if lhs === rhs { + return true + } + if lhs.emoji != rhs.emoji { + return false + } + if lhs.file.fileId != rhs.file.fileId { + return false + } + + return true + } + } + + public final class ItemGroup: Equatable { + public let id: AnyHashable + public let title: String? + public let items: [Item] + + public init( + id: AnyHashable, + title: String?, + items: [Item] + ) { + self.id = id + self.title = title + self.items = items + } + + public static func ==(lhs: ItemGroup, rhs: ItemGroup) -> Bool { + if lhs.id != rhs.id { + return false + } + if lhs.title != rhs.title { + return false + } + if lhs.items != rhs.items { + return false + } + return true + } + } + + public enum ItemLayoutType { + case compact + case detailed + } + + public let context: AccountContext + public let animationCache: AnimationCache + public let animationRenderer: MultiAnimationRenderer + public let inputInteraction: InputInteraction + public let itemGroups: [ItemGroup] + public let itemLayoutType: ItemLayoutType + + public init( + context: AccountContext, + animationCache: AnimationCache, + animationRenderer: MultiAnimationRenderer, + inputInteraction: InputInteraction, + itemGroups: [ItemGroup], + itemLayoutType: ItemLayoutType + ) { + self.context = context + self.animationCache = animationCache + self.animationRenderer = animationRenderer + self.inputInteraction = inputInteraction + self.itemGroups = itemGroups + self.itemLayoutType = itemLayoutType + } + + public static func ==(lhs: EmojiPagerContentComponent, rhs: EmojiPagerContentComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.animationCache !== rhs.animationCache { + return false + } + if lhs.animationRenderer !== rhs.animationRenderer { + return false + } + if lhs.inputInteraction !== rhs.inputInteraction { + return false + } + if lhs.itemGroups != rhs.itemGroups { + return false + } + if lhs.itemLayoutType != rhs.itemLayoutType { + return false + } + + return true + } + + public final class View: UIView, 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 { + var width: CGFloat + var containerInsets: UIEdgeInsets + var itemGroupLayouts: [ItemGroupLayout] + var itemSize: CGFloat + var horizontalSpacing: CGFloat + var verticalSpacing: CGFloat + var verticalGroupSpacing: CGFloat + var itemsPerRow: Int + var contentSize: CGSize + + init(width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], itemLayoutType: ItemLayoutType) { + self.width = width + self.containerInsets = containerInsets + + let minSpacing: CGFloat + switch itemLayoutType { + case .compact: + self.itemSize = 36.0 + self.verticalSpacing = 9.0 + minSpacing = 9.0 + case .detailed: + self.itemSize = 60.0 + self.verticalSpacing = 9.0 + minSpacing = 9.0 + } + + self.verticalGroupSpacing = 18.0 + + let itemHorizontalSpace = width - self.containerInsets.left - self.containerInsets.right + + self.itemsPerRow = Int((itemHorizontalSpace + minSpacing) / (self.itemSize + minSpacing)) + self.horizontalSpacing = floor((itemHorizontalSpace - self.itemSize * CGFloat(self.itemsPerRow)) / CGFloat(self.itemsPerRow - 1)) + + var verticalGroupOrigin: CGFloat = self.containerInsets.top + self.itemGroupLayouts = [] + for itemGroup in itemGroups { + var itemTopOffset: CGFloat = 0.0 + if itemGroup.hasTitle { + itemTopOffset += 24.0 + } + + let numRowsInGroup = (itemGroup.itemCount + (self.itemsPerRow - 1)) / self.itemsPerRow + let groupContentSize = CGSize(width: width, height: itemTopOffset + CGFloat(numRowsInGroup) * self.itemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) + self.itemGroupLayouts.append(ItemGroupLayout( + frame: CGRect(origin: CGPoint(x: 0.0, y: verticalGroupOrigin), size: groupContentSize), + itemTopOffset: itemTopOffset, + itemCount: itemGroup.itemCount + )) + verticalGroupOrigin += groupContentSize.height + self.verticalGroupSpacing + } + verticalGroupOrigin += self.containerInsets.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.containerInsets.left + CGFloat(column) * (self.itemSize + self.horizontalSpacing), + y: groupLayout.frame.minY + groupLayout.itemTopOffset + CGFloat(row) * (self.itemSize + self.verticalSpacing) + ), + size: CGSize( + width: self.itemSize, + height: self.itemSize + ) + ) + } + + func visibleItems(for rect: CGRect) -> [(groupIndex: Int, groupItems: Range)] { + var result: [(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.containerInsets.left, dy: -group.frame.minY - group.itemTopOffset) + 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 = min(group.itemCount - 1, (maxVisibleRow + 1) * self.itemsPerRow - 1) + + if maxVisibleIndex >= minVisibleIndex { + result.append(( + groupIndex: groupIndex, + groupItems: minVisibleIndex ..< (maxVisibleIndex + 1) + )) + } + } + + return result + } + } + + final class ItemLayer: MultiAnimationRenderTarget { + let item: Item + + private let file: TelegramMediaFile + private let placeholderColor: UIColor + private let size: CGSize + 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 var displayPlaceholder: Bool = false + + init( + item: Item, + context: AccountContext, + groupId: String, + attemptSynchronousLoad: Bool, + file: TelegramMediaFile, + cache: AnimationCache, + renderer: MultiAnimationRenderer, + placeholderColor: UIColor, + pointSize: CGSize + ) { + self.item = item + self.file = file + self.placeholderColor = placeholderColor + + 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 attemptSynchronousLoad { + if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { + self.displayPlaceholder = true + + if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: self.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, 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 + } + + 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 = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() + } + }) + } + + override public init(layer: Any) { + preconditionFailure() + } + + required public init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + deinit { + self.disposable?.dispose() + self.fetchDisposable?.dispose() + } + + override public 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 + } + + override func updateDisplayPlaceholder(displayPlaceholder: Bool) { + if self.displayPlaceholder == displayPlaceholder { + return + } + + self.displayPlaceholder = displayPlaceholder + let file = self.file + let size = self.size + let placeholderColor = self.placeholderColor + + Queue.concurrentDefaultQueue().async { [weak self] in + if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor) { + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + + if strongSelf.displayPlaceholder { + strongSelf.contents = image.cgImage + } + } + } + } + } + } + + private let scrollView: UIScrollView + + private var visibleItemLayers: [MediaId: ItemLayer] = [:] + private var visibleGroupHeaders: [AnyHashable: ComponentHostView] = [:] + private var ignoreScrolling: Bool = false + + private var component: EmojiPagerContentComponent? + private var pagerEnvironment: PagerComponentChildEnvironment? + private var theme: PresentationTheme? + private var itemLayout: ItemLayout? + + override init(frame: CGRect) { + self.scrollView = UIScrollView() + + super.init(frame: frame) + + 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 = false + self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.delegate = self + self.addSubview(self.scrollView) + + 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 let component = self.component, let item = self.item(atPoint: recognizer.location(in: self)), let itemView = self.visibleItemLayers[item.file.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 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) + } + + 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) { + 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 offsetToClosestEdge = min(offsetToTopEdge, offsetToBottomEdge) + + let relativeOffset = scrollView.contentOffset.y - previousScrollingOffsetValue + self.pagerEnvironment?.onChildScrollingUpdate(PagerComponentChildEnvironment.ContentScrollingUpdate( + relativeOffset: relativeOffset, + absoluteOffsetToClosestEdge: offsetToClosestEdge, + 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 theme = self.theme, let itemLayout = self.itemLayout else { + return + } + + var validIds = Set() + var validGroupHeaderIds = Set() + + for groupItems in itemLayout.visibleItems(for: self.scrollView.bounds) { + let itemGroup = component.itemGroups[groupItems.groupIndex] + let itemGroupLayout = itemLayout.itemGroupLayouts[groupItems.groupIndex] + + if let title = itemGroup.title { + validGroupHeaderIds.insert(itemGroup.id) + let groupHeaderView: ComponentHostView + if let current = self.visibleGroupHeaders[itemGroup.id] { + groupHeaderView = current + } else { + groupHeaderView = ComponentHostView() + self.visibleGroupHeaders[itemGroup.id] = groupHeaderView + self.scrollView.addSubview(groupHeaderView) + } + let groupHeaderSize = groupHeaderView.update( + transition: .immediate, + component: AnyComponent(Text( + text: title, font: Font.medium(12.0), color: theme.chat.inputMediaPanel.stickersSectionTextColor + )), + environment: {}, + containerSize: CGSize(width: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right, height: 100.0) + ) + groupHeaderView.frame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) + } + + for index in groupItems.groupItems.lowerBound ..< groupItems.groupItems.upperBound { + let item = itemGroup.items[index] + let itemId = item.file.fileId + validIds.insert(itemId) + + let itemLayer: ItemLayer + if let current = self.visibleItemLayers[itemId] { + itemLayer = current + } else { + itemLayer = ItemLayer(item: item, context: component.context, groupId: "keyboard", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, cache: component.animationCache, renderer: component.animationRenderer, placeholderColor: theme.chat.inputMediaPanel.stickersBackgroundColor, pointSize: CGSize(width: itemLayout.itemSize, height: itemLayout.itemSize)) + self.scrollView.layer.addSublayer(itemLayer) + self.visibleItemLayers[itemId] = itemLayer + } + + itemLayer.frame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: index) + itemLayer.isVisibleForAnimations = true + } + } + + var removedIds: [MediaId] = [] + for (id, itemLayer) in self.visibleItemLayers { + if !validIds.contains(id) { + removedIds.append(id) + itemLayer.removeFromSuperlayer() + } + } + for id in removedIds { + self.visibleItemLayers.removeValue(forKey: id) + } + + var removedGroupHeaderIds: [AnyHashable] = [] + for (id, groupHeaderView) in self.visibleGroupHeaders { + if !validGroupHeaderIds.contains(id) { + removedGroupHeaderIds.append(id) + groupHeaderView.removeFromSuperview() + } + } + for id in removedGroupHeaderIds { + self.visibleGroupHeaders.removeValue(forKey: id) + } + } + + func update(component: EmojiPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.component = component + self.theme = environment[EntityKeyboardChildEnvironment.self].value.theme + + let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value + self.pagerEnvironment = pagerEnvironment + + var itemGroups: [ItemGroupDescription] = [] + for itemGroup in component.itemGroups { + itemGroups.append(ItemGroupDescription( + hasTitle: itemGroup.title != nil, + itemCount: itemGroup.items.count + )) + } + + let itemLayout = ItemLayout(width: availableSize.width, containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top + 9.0, left: pagerEnvironment.containerInsets.left + 12.0, bottom: 9.0 + pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right + 12.0), itemGroups: itemGroups, itemLayoutType: component.itemLayoutType) + 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 + } + 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/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift new file mode 100644 index 0000000000..ae928d87ee --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -0,0 +1,214 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import BlurredBackgroundComponent +import BundleIconComponent + +public final class EntityKeyboardChildEnvironment: Equatable { + public let theme: PresentationTheme + + public init(theme: PresentationTheme) { + self.theme = theme + } + + public static func ==(lhs: EntityKeyboardChildEnvironment, rhs: EntityKeyboardChildEnvironment) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + + return true + } +} + +public final class EntityKeyboardComponent: Component { + public let theme: PresentationTheme + public let bottomInset: CGFloat + public let emojiContent: EmojiPagerContentComponent + public let stickerContent: EmojiPagerContentComponent + public let externalTopPanelContainer: UIView? + public let topPanelExtensionUpdated: (CGFloat, Transition) -> Void + + public init( + theme: PresentationTheme, + bottomInset: CGFloat, + emojiContent: EmojiPagerContentComponent, + stickerContent: EmojiPagerContentComponent, + externalTopPanelContainer: UIView?, + topPanelExtensionUpdated: @escaping (CGFloat, Transition) -> Void + ) { + self.theme = theme + self.bottomInset = bottomInset + self.emojiContent = emojiContent + self.stickerContent = stickerContent + self.externalTopPanelContainer = externalTopPanelContainer + self.topPanelExtensionUpdated = topPanelExtensionUpdated + } + + public static func ==(lhs: EntityKeyboardComponent, rhs: EntityKeyboardComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.bottomInset != rhs.bottomInset { + return false + } + if lhs.emojiContent != rhs.emojiContent { + return false + } + if lhs.stickerContent != rhs.stickerContent { + return false + } + if lhs.externalTopPanelContainer != rhs.externalTopPanelContainer { + return false + } + + return true + } + + public final class View: UIView { + private let pagerView: ComponentHostView + + private var component: EntityKeyboardComponent? + + override init(frame: CGRect) { + self.pagerView = ComponentHostView() + + super.init(frame: frame) + + self.clipsToBounds = 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 { + var contents: [AnyComponentWithIdentity<(EntityKeyboardChildEnvironment, PagerComponentChildEnvironment)>] = [] + var contentTopPanels: [AnyComponentWithIdentity] = [] + var contentIcons: [AnyComponentWithIdentity] = [] + var contentAccessoryRightButtons: [AnyComponentWithIdentity] = [] + + var topStickertems: [EntityKeyboardTopPanelComponent.Item] = [] + for itemGroup in component.stickerContent.itemGroups { + if !itemGroup.items.isEmpty { + topStickertems.append(EntityKeyboardTopPanelComponent.Item( + id: AnyHashable(itemGroup.items[0].file.fileId), + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.stickerContent.context, + file: itemGroup.items[0].file, + animationCache: component.stickerContent.animationCache, + animationRenderer: component.stickerContent.animationRenderer + )) + )) + } + } + contents.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(component.stickerContent))) + contentTopPanels.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(EntityKeyboardTopPanelComponent( + theme: component.theme, + items: topStickertems + )))) + contentIcons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputStickersIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )))) + 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: { + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) + + contents.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(component.emojiContent))) + var topEmojiItems: [EntityKeyboardTopPanelComponent.Item] = [] + for itemGroup in component.emojiContent.itemGroups { + if !itemGroup.items.isEmpty { + topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( + id: AnyHashable(itemGroup.items[0].file.fileId), + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.emojiContent.context, + file: itemGroup.items[0].file, + animationCache: component.emojiContent.animationCache, + animationRenderer: component.emojiContent.animationRenderer + )) + )) + } + } + + contentTopPanels.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(EntityKeyboardTopPanelComponent( + theme: component.theme, + items: topEmojiItems + )))) + contentIcons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputEmojiIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )))) + 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: { + component.emojiContent.inputInteraction.deleteBackwards() + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) + + let pagerSize = self.pagerView.update( + transition: transition, + component: AnyComponent(PagerComponent( + contentInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), + contents: contents, + contentTopPanels: contentTopPanels, + contentIcons: contentIcons, + contentAccessoryRightButtons: contentAccessoryRightButtons, + defaultId: "emoji", + contentBackground: AnyComponent(BlurredBackgroundComponent( + color: component.theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75) + )), + topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent( + theme: component.theme + )), + externalTopPanelContainer: component.externalTopPanelContainer, + bottomPanel: AnyComponent(EntityKeyboardBottomPanelComponent( + theme: component.theme, + bottomInset: component.bottomInset, + deleteBackwards: { [weak self] in + self?.component?.emojiContent.inputInteraction.deleteBackwards() + } + )), + panelStateUpdated: { panelState, transition in + component.topPanelExtensionUpdated(panelState.topPanelHeight, transition) + } + )), + environment: { + EntityKeyboardChildEnvironment(theme: component.theme) + }, + containerSize: availableSize + ) + transition.setFrame(view: self.pagerView, frame: CGRect(origin: CGPoint(), size: pagerSize)) + + 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/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift new file mode 100644 index 0000000000..82a2ec6b70 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift @@ -0,0 +1,293 @@ +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 content: AnyComponent + + init(content: AnyComponent) { + self.content = content + } + + static func ==(lhs: BottomPanelIconComponent, rhs: BottomPanelIconComponent) -> Bool { + if lhs.content != rhs.content { + return false + } + + return true + } + + final class View: UIView { + let contentView: ComponentHostView + + override init(frame: CGRect) { + self.contentView = ComponentHostView() + + super.init(frame: frame) + + self.addSubview(self.contentView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: BottomPanelIconComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let size = CGSize(width: 32.0, height: 32.0) + + let contentSize = self.contentView.update( + transition: transition, + component: component.content, + environment: {}, + containerSize: 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 bottomInset: CGFloat + let deleteBackwards: () -> Void + + init( + theme: PresentationTheme, + bottomInset: CGFloat, + deleteBackwards: @escaping () -> Void + ) { + self.theme = theme + self.bottomInset = bottomInset + self.deleteBackwards = deleteBackwards + } + + static func ==(lhs: EntityKeyboardBottomPanelComponent, rhs: EntityKeyboardBottomPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.bottomInset != rhs.bottomInset { + return false + } + + return true + } + + final class View: UIView { + private final class AccessoryButtonView { + let id: AnyHashable + let view: ComponentHostView + + init(id: AnyHashable, view: ComponentHostView) { + self.id = id + self.view = view + } + } + + private let backgroundView: BlurredBackgroundView + private let separatorView: UIView + 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 = 38.0 + let height = intrinsicHeight + component.bottomInset + + let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value + let activeContentId = panelEnvironment.activeContentId + + 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 { + rightAccessoryButton = current + } else { + rightAccessoryButtonTransition = .immediate + rightAccessoryButton = AccessoryButtonView(id: rightAccessoryButtonComponent.id, view: ComponentHostView()) + self.rightAccessoryButton = rightAccessoryButton + self.addSubview(rightAccessoryButton.view) + } + + let rightAccessoryButtonSize = rightAccessoryButton.view.update( + transition: rightAccessoryButtonTransition, + component: AnyComponent(Button( + content: rightAccessoryButtonComponent.component, + action: { [weak self] in + self?.component?.deleteBackwards() + } + ).minSize(CGSize(width: intrinsicHeight, height: intrinsicHeight))), + environment: {}, + containerSize: CGSize(width: .greatestFiniteMagnitude, height: intrinsicHeight) + ) + rightAccessoryButtonTransition.setFrame(view: rightAccessoryButton.view, frame: CGRect(origin: CGPoint(x: availableSize.width - 2.0 - rightAccessoryButtonSize.width, y: 2.0), size: rightAccessoryButtonSize)) + } else { + self.rightAccessoryButton = nil + } + + if previousRightAccessoryButton !== 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 + + 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( + content: icon.component + )), + environment: {}, + containerSize: CGSize(width: 32.0, height: 32.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) + 2.0) + 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) + } + + 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..875bdd0156 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -0,0 +1,136 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox + +final class EntityKeyboardTopContainerPanelComponent: Component { + typealias EnvironmentType = PagerComponentPanelEnvironment + + let theme: PresentationTheme + + init( + theme: PresentationTheme + ) { + self.theme = theme + } + + static func ==(lhs: EntityKeyboardTopContainerPanelComponent, rhs: EntityKeyboardTopContainerPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + + return true + } + + final class View: UIView { + private var panelViews: [AnyHashable: ComponentHostView] = [:] + + private var component: EntityKeyboardTopContainerPanelComponent? + private var panelEnvironment: PagerComponentPanelEnvironment? + private weak var state: EmptyComponentState? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + 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 = 41.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: 0.0), size: CGSize(width: availableSize.width, height: intrinsicHeight)) + + 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: ComponentHostView + if let current = self.panelViews[panel.id] { + panelView = current + } else { + panelTransition = .immediate + panelView = ComponentHostView() + self.panelViews[panel.id] = panelView + self.addSubview(panelView) + } + + let _ = panelView.update( + transition: panelTransition, + component: panel.component, + environment: {}, + containerSize: panelFrame.size + ) + if isInBounds { + transition.animatePosition(view: panelView, from: CGPoint(x: transitionOffsetFraction * availableSize.width, y: 0.0), to: CGPoint(), additive: true, completion: nil) + } + panelTransition.setFrame(view: panelView, 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.removeFromSuperview() + } + } + for id in removedPanelIds { + self.panelViews.removeValue(forKey: id) + } + + 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/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift new file mode 100644 index 0000000000..9e7732f6c4 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -0,0 +1,315 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import PagerComponent +import TelegramPresentationData +import TelegramCore +import Postbox +import AnimationCache +import MultiAnimationRenderer +import AccountContext + +final class EntityKeyboardAnimationTopPanelComponent: Component { + typealias EnvironmentType = Empty + + let context: AccountContext + let file: TelegramMediaFile + let animationCache: AnimationCache + let animationRenderer: MultiAnimationRenderer + + init( + context: AccountContext, + file: TelegramMediaFile, + animationCache: AnimationCache, + animationRenderer: MultiAnimationRenderer + ) { + self.context = context + self.file = file + self.animationCache = animationCache + self.animationRenderer = animationRenderer + } + + 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.animationCache !== rhs.animationCache { + return false + } + if lhs.animationRenderer !== rhs.animationRenderer { + return false + } + + return true + } + + final class View: UIView { + var itemLayer: EmojiPagerContentComponent.View.ItemLayer? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: EntityKeyboardAnimationTopPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + if self.itemLayer == nil { + let itemLayer = EmojiPagerContentComponent.View.ItemLayer( + item: EmojiPagerContentComponent.Item( + emoji: "", + file: component.file + ), + context: component.context, + groupId: "topPanel", + attemptSynchronousLoad: false, + file: component.file, + cache: component.animationCache, + renderer: component.animationRenderer, + placeholderColor: .lightGray, + pointSize: CGSize(width: 28.0, height: 28.0) + ) + self.itemLayer = itemLayer + self.layer.addSublayer(itemLayer) + itemLayer.frame = CGRect(origin: CGPoint(), size: CGSize(width: 28.0, height: 28.0)) + itemLayer.isVisibleForAnimations = true + } + + return CGSize(width: 28.0, height: 28.0) + } + } + + 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 EntityKeyboardTopPanelComponent: Component { + typealias EnvironmentType = Empty + + final class Item: Equatable { + let id: AnyHashable + let content: AnyComponent + + init(id: AnyHashable, content: AnyComponent) { + self.id = id + self.content = content + } + + static func ==(lhs: Item, rhs: Item) -> Bool { + if lhs.id != rhs.id { + return false + } + if lhs.content != rhs.content { + return false + } + + return true + } + } + + let theme: PresentationTheme + let items: [Item] + + init( + theme: PresentationTheme, + items: [Item] + ) { + self.theme = theme + self.items = items + } + + static func ==(lhs: EntityKeyboardTopPanelComponent, rhs: EntityKeyboardTopPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.items != rhs.items { + return false + } + + return true + } + + final class View: UIView, UIScrollViewDelegate { + private struct ItemLayout { + let sideInset: CGFloat = 7.0 + let itemSize: CGFloat = 32.0 + let innerItemSize: CGFloat = 28.0 + let itemSpacing: CGFloat = 15.0 + let itemCount: Int + let contentSize: CGSize + + init(itemCount: Int) { + self.itemCount = itemCount + self.contentSize = CGSize(width: sideInset * 2.0 + CGFloat(itemCount) * self.itemSize + CGFloat(max(0, itemCount - 1)) * itemSpacing, height: 41.0) + } + + func containerFrame(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 contentFrame(at index: Int) -> CGRect { + var frame = self.containerFrame(at: index) + frame.origin.x += floor((self.itemSize - self.innerItemSize)) / 2.0 + frame.origin.y += floor((self.itemSize - self.innerItemSize)) / 2.0 + frame.size = CGSize(width: self.innerItemSize, height: self.innerItemSize) + return frame + } + + func visibleItemRange(for rect: CGRect) -> (minIndex: Int, maxIndex: Int) { + let offsetRect = rect.offsetBy(dx: -self.sideInset, dy: 0.0) + var minVisibleColumn = Int(floor((offsetRect.minX - self.itemSpacing) / (self.itemSize + self.itemSpacing))) + minVisibleColumn = max(0, minVisibleColumn) + let maxVisibleColumn = Int(ceil((offsetRect.maxX - self.itemSpacing) / (self.itemSize + self.itemSpacing))) + + let minVisibleIndex = minVisibleColumn + let maxVisibleIndex = min(maxVisibleColumn, self.itemCount - 1) + + return (minVisibleIndex, maxVisibleIndex) + } + } + + private let scrollView: UIScrollView + private var itemViews: [AnyHashable: ComponentHostView] = [:] + private var highlightedIconBackgroundView: UIView + + private var itemLayout: ItemLayout? + private var ignoreScrolling: Bool = false + + private var component: EntityKeyboardTopPanelComponent? + + override init(frame: CGRect) { + self.scrollView = UIScrollView() + + self.highlightedIconBackgroundView = UIView() + self.highlightedIconBackgroundView.isUserInteractionEnabled = false + self.highlightedIconBackgroundView.layer.cornerRadius = 10.0 + self.highlightedIconBackgroundView.clipsToBounds = true + + super.init(frame: frame) + + 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 = false + self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.delegate = self + self.addSubview(self.scrollView) + + self.scrollView.addSubview(self.highlightedIconBackgroundView) + + self.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in + guard let strongSelf = self else { + return false + } + return strongSelf.scrollView.contentOffset.x > 0.0 + } + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public func scrollViewDidScroll(_ scrollView: UIScrollView) { + if self.ignoreScrolling { + return + } + + self.updateVisibleItems(attemptSynchronousLoads: false) + } + + private func updateVisibleItems(attemptSynchronousLoads: Bool) { + guard let component = self.component, let itemLayout = self.itemLayout else { + return + } + + var validIds = Set() + let visibleItemRange = itemLayout.visibleItemRange(for: self.scrollView.bounds) + if !component.items.isEmpty && visibleItemRange.maxIndex >= visibleItemRange.minIndex { + for index in visibleItemRange.minIndex ... visibleItemRange.maxIndex { + let item = component.items[index] + validIds.insert(item.id) + + let itemView: ComponentHostView + if let current = self.itemViews[item.id] { + itemView = current + } else { + itemView = ComponentHostView() + self.scrollView.addSubview(itemView) + self.itemViews[item.id] = itemView + } + + let itemFrame = itemLayout.contentFrame(at: index) + itemView.frame = itemFrame + let _ = itemView.update( + transition: .immediate, + component: item.content, + environment: {}, + containerSize: itemFrame.size + ) + } + } + 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 + + let intrinsicHeight: CGFloat = 41.0 + let height = intrinsicHeight + + let itemLayout = ItemLayout(itemCount: component.items.count) + self.itemLayout = itemLayout + + self.ignoreScrolling = true + transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: intrinsicHeight))) + if self.scrollView.contentSize != itemLayout.contentSize { + self.scrollView.contentSize = itemLayout.contentSize + } + self.ignoreScrolling = false + + if let _ = component.items.first { + self.highlightedIconBackgroundView.isHidden = false + let itemFrame = itemLayout.containerFrame(at: 0) + transition.setFrame(view: self.highlightedIconBackgroundView, frame: itemFrame) + } + + self.updateVisibleItems(attemptSynchronousLoads: true) + + 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/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index 97fb1cee2c..d399ea98cc 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -5,8 +5,8 @@ import Display import AnimationCache 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(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable + func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool } open class MultiAnimationRenderTarget: SimpleLayer { @@ -28,6 +28,9 @@ open class MultiAnimationRenderTarget: SimpleLayer { f() } } + + open func updateDisplayPlaceholder(displayPlaceholder: Bool) { + } } private func convertFrameToImage(frame: AnimationCacheItemFrame) -> UIImage? { @@ -126,6 +129,7 @@ private final class ItemAnimationContext { private var displayLink: ConstantDisplayLinkAnimator? private var frameIndex: Int = 0 private var item: AnimationCacheItem? + private var frameSkip: Int private var currentFrameGroup: FrameGroup? private var isLoadingFrameGroup: Bool = false @@ -140,17 +144,26 @@ 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, frameSkip: Int, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { self.cache = cache + self.frameSkip = frameSkip 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() + + if result.item == nil { + for target in strongSelf.targets.copyItems() { + if let target = target.value { + target.updateDisplayPlaceholder(displayPlaceholder: true) + } + } + } } }) } @@ -165,6 +178,7 @@ private final class ItemAnimationContext { 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 } @@ -210,11 +224,12 @@ private final class ItemAnimationContext { } 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: 2) + let currentFrameGroup = FrameGroup(item: item, baseFrameIndex: currentFrame, count: possibleCounts[countIndex], skip: frameSkip) return { guard let strongSelf = self else { @@ -236,12 +251,15 @@ private final class ItemAnimationContext { } if advanceFrame { - self.frameIndex += 2 + self.frameIndex += self.frameSkip } if let currentFrameGroup = self.currentFrameGroup, let contentsRect = currentFrameGroup.contentsRect(index: currentFrame) { for target in self.targets.copyItems() { - target.value?.contentsRect = contentsRect + if let target = target.value { + target.updateDisplayPlaceholder(displayPlaceholder: false) + target.contentsRect = contentsRect + } } } @@ -251,6 +269,7 @@ private final class ItemAnimationContext { public final class MultiAnimationRendererImpl: MultiAnimationRenderer { private final class GroupContext { + private var frameSkip: Int private let stateUpdated: () -> Void private var itemContexts: [String: ItemAnimationContext] = [:] @@ -263,16 +282,17 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - init(stateUpdated: @escaping () -> Void) { + init(frameSkip: Int, stateUpdated: @escaping () -> Void) { + self.frameSkip = frameSkip 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 itemContext: ItemAnimationContext if let current = self.itemContexts[itemId] { itemContext = current } else { - itemContext = ItemAnimationContext(cache: cache, itemId: itemId, fetch: fetch, stateUpdated: { [weak self] in + itemContext = ItemAnimationContext(cache: cache, itemId: itemId, size: size, frameSkip: self.frameSkip, fetch: fetch, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -318,8 +338,8 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String) -> Bool { - if let item = cache.getSynchronously(sourceId: 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 } @@ -359,6 +379,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } private var groupContexts: [String: GroupContext] = [:] + private var frameSkip: Int private var displayLink: ConstantDisplayLinkAnimator? private(set) var isPlaying: Bool = false { @@ -372,7 +393,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } strongSelf.animationTick() } - self.displayLink?.frameInterval = 2 + self.displayLink?.frameInterval = self.frameSkip self.displayLink?.isPaused = false } } else { @@ -386,14 +407,19 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } 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, fetch: @escaping (AnimationCacheItemWriter) -> Disposable) -> Disposable { + 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(stateUpdated: { [weak self] in + groupContext = GroupContext(frameSkip: self.frameSkip, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -402,19 +428,19 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { self.groupContexts[groupId] = 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(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(stateUpdated: { [weak self] in + groupContext = GroupContext(frameSkip: self.frameSkip, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -423,7 +449,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { self.groupContexts[groupId] = groupContext } - return groupContext.loadFirstFrameSynchronously(target: target, cache: cache, itemId: itemId) + return groupContext.loadFirstFrameSynchronously(target: target, cache: cache, itemId: itemId, size: size) } private func updateIsPlaying() { 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..f93f8f8fb7 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_clear.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/ic_clear.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/ic_clear.pdf new file mode 100644 index 0000000000..559ad92734 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/ic_clear.pdf @@ -0,0 +1,107 @@ +%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 3.180420 6.169983 cm +0.000000 0.000000 0.000000 scn +7.131522 16.439991 m +8.015658 17.225891 9.157463 17.660004 10.340398 17.660004 c +19.819601 17.660004 l +22.487137 17.660004 24.649601 15.497540 24.649601 12.830004 c +24.649601 4.830004 l +24.649601 2.162468 22.487137 0.000004 19.819601 0.000004 c +10.340399 0.000004 l +9.157463 0.000004 8.015657 0.434116 7.131521 1.220016 c +0.949850 6.714835 l +-0.316617 7.840584 -0.316617 9.819424 0.949850 10.945172 c +7.131522 16.439991 l +h +10.340398 16.000004 m +9.564020 16.000004 8.814637 15.715089 8.234365 15.199291 c +2.052694 9.704473 l +1.529102 9.239058 1.529102 8.420950 2.052694 7.955535 c +8.234365 2.460716 l +8.814637 1.944919 9.564020 1.660004 10.340399 1.660004 c +19.819601 1.660004 l +21.570343 1.660004 22.989601 3.079261 22.989601 4.830004 c +22.989601 12.830004 l +22.989601 14.580747 21.570343 16.000004 19.819601 16.000004 c +10.340398 16.000004 l +h +10.732702 12.916903 m +11.056838 13.241037 11.582364 13.241037 11.906500 12.916903 c +14.819601 10.003801 l +17.732702 12.916903 l +18.056837 13.241037 18.582365 13.241037 18.906500 12.916903 c +19.230635 12.592768 19.230635 12.067240 18.906500 11.743105 c +15.993399 8.830004 l +18.906500 5.916903 l +19.230635 5.592768 19.230635 5.067240 18.906500 4.743105 c +18.582365 4.418970 18.056837 4.418970 17.732702 4.743105 c +14.819601 7.656206 l +11.906500 4.743105 l +11.582364 4.418970 11.056838 4.418970 10.732702 4.743105 c +10.408567 5.067241 10.408567 5.592767 10.732702 5.916903 c +13.645803 8.830004 l +10.732702 11.743105 l +10.408567 12.067240 10.408567 12.592768 10.732702 12.916903 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1651 +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 +0000001741 00000 n +0000001764 00000 n +0000001937 00000 n +0000002011 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2070 +%%EOF \ No newline at end of file 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..8d1829694d --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_emoji.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/ic_emoji.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/ic_emoji.pdf new file mode 100644 index 0000000000..51dd673605 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/ic_emoji.pdf @@ -0,0 +1,123 @@ +%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 7.292999 5.741058 cm +0.000000 0.000000 0.000000 scn +7.706251 7.052563 m +9.859218 7.052563 11.806032 7.518116 13.204300 7.852490 c +14.570075 8.179095 15.412500 8.380550 15.412500 7.900764 c +15.412500 3.644719 11.962295 0.194514 7.706251 0.194514 c +3.450206 0.194514 0.000000 3.644719 0.000000 7.900764 c +0.000000 8.380550 0.842425 8.179095 2.208200 7.852490 c +3.606467 7.518116 5.553283 7.052563 7.706251 7.052563 c +h +12.468611 6.348519 m +11.392131 6.066849 9.742197 5.635127 7.697002 5.635127 c +5.651808 5.635127 4.001874 6.066849 2.925394 6.348519 c +2.030582 6.582655 1.532002 6.713113 1.532002 6.405752 c +1.532002 3.455799 6.013958 3.323253 7.697002 3.323253 c +9.586575 3.323253 13.862001 3.456314 13.862001 6.405752 c +13.862001 6.713113 13.363423 6.582655 12.468611 6.348519 c +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 2.669983 2.669983 cm +0.000000 0.000000 0.000000 scn +12.330000 23.000004 m +6.437122 23.000004 1.660000 18.222881 1.660000 12.330004 c +1.660000 6.437126 6.437122 1.660004 12.330000 1.660004 c +18.222878 1.660004 23.000000 6.437126 23.000000 12.330004 c +23.000000 18.222881 18.222878 23.000004 12.330000 23.000004 c +h +0.000000 12.330004 m +0.000000 19.139675 5.520329 24.660004 12.330000 24.660004 c +19.139671 24.660004 24.660000 19.139675 24.660000 12.330004 c +24.660000 5.520332 19.139671 0.000004 12.330000 0.000004 c +5.520329 0.000004 0.000000 5.520332 0.000000 12.330004 c +h +f* +n +Q +q +1.000000 0.000000 -0.000000 1.000000 10.000000 16.250000 cm +0.000000 0.000000 0.000000 scn +3.000000 1.750000 m +3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c +0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c +0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c +2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 17.000000 16.250000 cm +0.000000 0.000000 0.000000 scn +3.000000 1.750000 m +3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c +0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c +0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c +2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c +h +f +n +Q + +endstream +endobj + +3 0 obj + 2167 +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 +0000002257 00000 n +0000002280 00000 n +0000002453 00000 n +0000002527 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2586 +%%EOF \ No newline at end of file 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..35222f8570 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_gifs.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/ic_gifs.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/ic_gifs.pdf new file mode 100644 index 0000000000..410ff918fa --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/ic_gifs.pdf @@ -0,0 +1,128 @@ +%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.669983 2.670013 cm +0.000000 0.000000 0.000000 scn +12.330000 22.999989 m +6.437122 22.999989 1.660000 18.222866 1.660000 12.329988 c +1.660000 6.437111 6.437122 1.659988 12.330000 1.659988 c +18.222878 1.659988 23.000000 6.437111 23.000000 12.329988 c +23.000000 18.222866 18.222878 22.999989 12.330000 22.999989 c +h +0.000000 12.329988 m +0.000000 19.139660 5.520329 24.659988 12.330000 24.659988 c +19.139671 24.659988 24.660000 19.139660 24.660000 12.329988 c +24.660000 5.520317 19.139671 -0.000011 12.330000 -0.000011 c +5.520329 -0.000011 0.000000 5.520317 0.000000 12.329988 c +h +17.108725 15.659992 m +17.129999 15.659988 l +18.830000 15.659988 l +19.288397 15.659988 19.660000 15.288384 19.660000 14.829988 c +19.660000 14.371593 19.288397 13.999989 18.830000 13.999989 c +17.160000 13.999989 l +17.160000 13.159988 l +18.830000 13.159988 l +19.288397 13.159988 19.660000 12.788384 19.660000 12.329988 c +19.660000 11.871593 19.288397 11.499989 18.830000 11.499989 c +17.160000 11.499989 l +17.160000 9.829988 l +17.160000 9.371592 16.788397 8.999989 16.330000 8.999989 c +15.871604 8.999989 15.500000 9.371592 15.500000 9.829988 c +15.500000 12.329988 l +15.500000 14.029988 l +15.499996 14.051264 l +15.499962 14.172362 15.499924 14.307926 15.509568 14.425976 c +15.520575 14.560680 15.548159 14.743810 15.644961 14.933796 c +15.772472 15.184052 15.975937 15.387516 16.226192 15.515027 c +16.416180 15.611830 16.599308 15.639414 16.734013 15.650420 c +16.852062 15.660065 16.987627 15.660027 17.108725 15.659992 c +h +13.330000 15.659988 m +13.788396 15.659988 14.160000 15.288384 14.160000 14.829988 c +14.160000 9.829988 l +14.160000 9.371592 13.788396 8.999989 13.330000 8.999989 c +12.871604 8.999989 12.500000 9.371592 12.500000 9.829988 c +12.500000 14.829988 l +12.500000 15.288384 12.871604 15.659988 13.330000 15.659988 c +h +8.330000 15.659988 m +6.490891 15.659988 5.000000 14.169097 5.000000 12.329988 c +5.000000 10.490880 6.490891 8.999989 8.330000 8.999989 c +9.670162 8.999989 11.076591 9.880583 11.385777 11.507551 c +11.393431 11.547824 l +11.397078 11.588655 l +11.427523 11.929440 l +11.486586 12.590580 10.965777 13.159988 10.302004 13.159988 c +9.330000 13.159988 l +8.871603 13.159988 8.500000 12.788385 8.500000 12.329988 c +8.500000 11.871592 8.871603 11.499989 9.330000 11.499989 c +9.657213 11.499989 l +9.421404 10.962639 8.887941 10.659988 8.330000 10.659988 c +7.407684 10.659988 6.660000 11.407673 6.660000 12.329988 c +6.660000 13.252304 7.407684 13.999989 8.330000 13.999989 c +8.609308 13.999989 8.870320 13.932076 9.099771 13.812578 c +9.506336 13.600842 10.007568 13.758780 10.219306 14.165344 c +10.431044 14.571908 10.273106 15.073140 9.866541 15.284878 c +9.405935 15.524760 8.882543 15.659988 8.330000 15.659988 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 2783 +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 +0000002873 00000 n +0000002896 00000 n +0000003069 00000 n +0000003143 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +3202 +%%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..186f60078b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_search.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/ic_search.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/ic_search.pdf new file mode 100644 index 0000000000..1e6ad4f2b4 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/ic_search.pdf @@ -0,0 +1,82 @@ +%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.999991 4.221268 cm +0.000000 0.000000 0.000000 scn +2.000000 12.278740 m +2.000000 15.868591 4.910149 18.778740 8.500000 18.778740 c +12.089850 18.778740 15.000000 15.868591 15.000000 12.278740 c +15.000000 8.688890 12.089850 5.778740 8.500000 5.778740 c +4.910149 5.778740 2.000000 8.688890 2.000000 12.278740 c +h +8.500000 20.778740 m +3.805580 20.778740 0.000000 16.973160 0.000000 12.278740 c +0.000000 7.584319 3.805580 3.778740 8.500000 3.778740 c +10.427133 3.778740 12.204475 4.420067 13.630243 5.500938 c +18.676220 0.454960 l +19.131182 0.000000 19.868818 0.000000 20.323780 0.454960 c +20.778740 0.909922 20.778740 1.647558 20.323780 2.102520 c +15.277802 7.148497 l +16.358673 8.574265 17.000000 10.351607 17.000000 12.278740 c +17.000000 16.973160 13.194421 20.778740 8.500000 20.778740 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 864 +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 +0000000954 00000 n +0000000976 00000 n +0000001149 00000 n +0000001223 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1282 +%%EOF \ No newline at end of file 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..6044f8aa11 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_tools.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf new file mode 100644 index 0000000000..702905fc0c --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf @@ -0,0 +1,177 @@ +%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.459991 2.485321 cm +0.000000 0.000000 0.000000 scn +11.355469 0.000000 m +13.722656 0.000000 l +14.625000 0.000000 15.316406 0.550781 15.527344 1.417969 c +16.031250 3.609375 l +16.406250 3.738281 l +18.316406 2.566406 l +19.078125 2.085938 19.957031 2.203125 20.601562 2.847656 c +22.242188 4.476562 l +22.886719 5.121094 23.003906 6.011719 22.523438 6.761719 c +21.328125 8.660156 l +21.468750 9.011719 l +23.660156 9.527344 l +24.515625 9.738281 25.078125 10.441406 25.078125 11.332031 c +25.078125 13.652344 l +25.078125 14.542969 24.527344 15.246094 23.660156 15.457031 c +21.492188 15.984375 l +21.339844 16.359375 l +22.535156 18.257812 l +23.015625 19.007812 22.898438 19.886719 22.253906 20.542969 c +20.613281 22.183594 l +19.980469 22.816406 19.101562 22.933594 18.339844 22.464844 c +16.429688 21.292969 l +16.031250 21.445312 l +15.527344 23.636719 l +15.316406 24.503906 14.625000 25.054688 13.722656 25.054688 c +11.355469 25.054688 l +10.453125 25.054688 9.761719 24.503906 9.550781 23.636719 c +9.035156 21.445312 l +8.636719 21.292969 l +6.738281 22.464844 l +5.976562 22.933594 5.085938 22.816406 4.453125 22.183594 c +2.824219 20.542969 l +2.179688 19.886719 2.050781 19.007812 2.542969 18.257812 c +3.726562 16.359375 l +3.585938 15.984375 l +1.417969 15.457031 l +0.550781 15.246094 0.000000 14.542969 0.000000 13.652344 c +0.000000 11.332031 l +0.000000 10.441406 0.562500 9.738281 1.417969 9.527344 c +3.609375 9.011719 l +3.738281 8.660156 l +2.554688 6.761719 l +2.062500 6.011719 2.191406 5.121094 2.835938 4.476562 c +4.464844 2.847656 l +5.109375 2.203125 6.000000 2.085938 6.761719 2.566406 c +8.660156 3.738281 l +9.035156 3.609375 l +9.550781 1.417969 l +9.761719 0.550781 10.453125 0.000000 11.355469 0.000000 c +h +11.542969 1.828125 m +11.343750 1.828125 11.238281 1.910156 11.203125 2.097656 c +10.500000 5.003906 l +9.785156 5.179688 9.117188 5.460938 8.613281 5.777344 c +6.058594 4.207031 l +5.917969 4.101562 5.765625 4.125000 5.625000 4.265625 c +4.242188 5.648438 l +4.113281 5.777344 4.101562 5.917969 4.195312 6.082031 c +5.765625 8.613281 l +5.496094 9.105469 5.191406 9.773438 5.003906 10.488281 c +2.097656 11.179688 l +1.910156 11.214844 1.828125 11.320312 1.828125 11.519531 c +1.828125 13.476562 l +1.828125 13.687500 1.898438 13.781250 2.097656 13.816406 c +4.992188 14.519531 l +5.179688 15.281250 5.531250 15.972656 5.742188 16.406250 c +4.183594 18.937500 l +4.078125 19.113281 4.089844 19.253906 4.218750 19.394531 c +5.613281 20.753906 l +5.753906 20.894531 5.882812 20.917969 6.058594 20.812500 c +8.589844 19.277344 l +9.093750 19.558594 9.808594 19.851562 10.511719 20.050781 c +11.203125 22.957031 l +11.238281 23.144531 11.343750 23.226562 11.542969 23.226562 c +13.535156 23.226562 l +13.734375 23.226562 13.839844 23.144531 13.863281 22.957031 c +14.578125 20.027344 l +15.304688 19.839844 15.937500 19.546875 16.464844 19.265625 c +19.007812 20.812500 l +19.195312 20.917969 19.312500 20.894531 19.464844 20.753906 c +20.847656 19.394531 l +20.988281 19.253906 20.988281 19.113281 20.882812 18.937500 c +19.324219 16.406250 l +19.546875 15.972656 19.886719 15.281250 20.074219 14.519531 c +22.980469 13.816406 l +23.167969 13.781250 23.250000 13.687500 23.250000 13.476562 c +23.250000 11.519531 l +23.250000 11.320312 23.156250 11.214844 22.980469 11.179688 c +20.062500 10.488281 l +19.875000 9.773438 19.582031 9.105469 19.300781 8.613281 c +20.871094 6.082031 l +20.964844 5.917969 20.964844 5.777344 20.824219 5.648438 c +19.453125 4.265625 l +19.300781 4.125000 19.160156 4.101562 19.007812 4.207031 c +16.453125 5.777344 l +15.949219 5.460938 15.292969 5.179688 14.578125 5.003906 c +13.863281 2.097656 l +13.839844 1.910156 13.734375 1.828125 13.535156 1.828125 c +11.542969 1.828125 l +h +12.539062 8.050781 m +14.988281 8.050781 17.003906 10.066406 17.003906 12.527344 c +17.003906 14.964844 14.988281 16.980469 12.539062 16.980469 c +10.089844 16.980469 8.062500 14.964844 8.062500 12.527344 c +8.062500 10.078125 10.078125 8.050781 12.539062 8.050781 c +h +12.539062 9.867188 m +11.085938 9.867188 9.890625 11.062500 9.890625 12.527344 c +9.890625 13.968750 11.085938 15.164062 12.539062 15.164062 c +13.968750 15.164062 15.164062 13.968750 15.164062 12.527344 c +15.164062 11.074219 13.968750 9.867188 12.539062 9.867188 c +h +f +n +Q + +endstream +endobj + +3 0 obj + 4265 +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 +0000004355 00000 n +0000004378 00000 n +0000004551 00000 n +0000004625 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +4684 +%%EOF \ No newline at end of file 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..0f561e6972 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ic_stickers.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/ic_stickers.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/ic_stickers.pdf new file mode 100644 index 0000000000..24ac31eb23 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/ic_stickers.pdf @@ -0,0 +1,431 @@ +%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.336044 cm +0.000000 0.000000 0.000000 scn +12.629680 1.768461 m +12.783916 0.952917 l +12.629680 1.768461 l +h +16.593809 4.257765 m +17.180708 3.670866 l +16.593809 4.257765 l +h +14.895066 2.706814 m +14.427451 3.392551 l +14.895066 2.706814 l +h +21.895494 11.034276 m +22.711039 10.880039 l +21.895494 11.034276 l +h +19.406189 7.070145 m +18.819290 7.657043 l +19.406189 7.070145 l +h +20.957142 8.768889 m +20.271404 9.236505 l +20.957142 8.768889 l +h +0.483443 6.107693 m +-0.289235 5.804592 l +0.483443 6.107693 l +h +4.443737 2.147398 m +4.140636 1.374722 l +4.443737 2.147398 l +h +21.516558 19.220219 m +22.289234 19.523319 l +21.516558 19.220219 l +h +3.962814 22.970737 m +3.602690 23.718542 l +3.962814 22.970737 l +h +0.693218 19.701141 m +-0.054586 20.061266 l +0.693218 19.701141 l +h +11.000000 22.833956 m +11.668203 22.833956 l +11.668203 24.493956 l +11.000000 24.493956 l +11.000000 22.833956 l +h +0.830000 11.995752 m +0.830000 12.663956 l +-0.830000 12.663956 l +-0.830000 11.995752 l +0.830000 11.995752 l +h +18.819290 7.657043 m +16.006910 4.844664 l +17.180708 3.670866 l +19.993088 6.483246 l +18.819290 7.657043 l +h +10.331797 0.833956 m +11.464174 0.833956 12.137112 0.830593 12.783916 0.952917 c +12.475444 2.584003 l +12.017082 2.497318 11.526485 2.493956 10.331797 2.493956 c +10.331797 0.833956 l +h +16.006910 4.844664 m +15.162139 3.999891 14.812858 3.655367 14.427451 3.392551 c +15.362681 2.021076 l +15.906537 2.391941 16.379997 2.870155 17.180708 3.670866 c +16.006910 4.844664 l +h +12.783916 0.952917 m +13.707870 1.127657 14.585788 1.491302 15.362681 2.021076 c +14.427451 3.392551 l +13.839379 2.991537 13.174834 2.716274 12.475444 2.584003 c +12.783916 0.952917 l +h +21.170000 13.332159 m +21.170000 12.137469 21.166637 11.646873 21.079952 11.188512 c +22.711039 10.880039 l +22.833363 11.526844 22.830000 12.199781 22.830000 13.332159 c +21.170000 13.332159 l +h +19.993088 6.483246 m +20.793798 7.283958 21.272015 7.757419 21.642879 8.301274 c +20.271404 9.236505 l +20.008589 8.851098 19.664062 8.501816 18.819290 7.657043 c +19.993088 6.483246 l +h +21.079952 11.188512 m +20.947681 10.489121 20.672419 9.824576 20.271404 9.236505 c +21.642879 8.301274 l +22.172653 9.078168 22.536299 9.956086 22.711039 10.880039 c +21.079952 11.188512 l +h +-0.830000 11.995752 m +-0.830000 10.454670 -0.830408 9.259295 -0.767823 8.296148 c +-0.704785 7.326029 -0.575355 6.533985 -0.289235 5.804592 c +1.256120 6.410791 l +1.058798 6.913816 0.946507 7.513920 0.888684 8.403788 c +0.830408 9.300627 0.830000 10.433072 0.830000 11.995752 c +-0.830000 11.995752 l +h +10.331797 2.493956 m +8.769116 2.493956 7.636671 2.494364 6.739831 2.552639 c +5.849965 2.610462 5.249860 2.722754 4.746836 2.920076 c +4.140636 1.374722 l +4.870029 1.088600 5.662074 0.959171 6.632193 0.896133 c +7.595339 0.833548 8.790714 0.833956 10.331797 0.833956 c +10.331797 2.493956 l +h +-0.289235 5.804592 m +0.506586 3.775846 2.111891 2.170542 4.140636 1.374722 c +4.746836 2.920076 l +3.148195 3.547178 1.883223 4.812151 1.256120 6.410791 c +-0.289235 5.804592 l +h +11.668203 22.833956 m +13.230883 22.833956 14.363329 22.833548 15.260168 22.775272 c +16.150036 22.717449 16.750139 22.605158 17.253164 22.407835 c +17.859364 23.953190 l +17.129971 24.239311 16.337927 24.368740 15.367807 24.431778 c +14.404661 24.494364 13.209285 24.493956 11.668203 24.493956 c +11.668203 22.833956 l +h +22.830000 13.332159 m +22.830000 14.873241 22.830408 16.068617 22.767822 17.031763 c +22.704784 18.001881 22.575356 18.793926 22.289234 19.523319 c +20.743879 18.917120 l +20.941202 18.414095 21.053493 17.813992 21.111317 16.924124 c +21.169592 16.027285 21.170000 14.894838 21.170000 13.332159 c +22.830000 13.332159 l +h +17.253164 22.407835 m +18.851805 21.780733 20.116777 20.515760 20.743879 18.917120 c +22.289234 19.523319 l +21.493414 21.552065 19.888109 23.157370 17.859364 23.953190 c +17.253164 22.407835 l +h +11.000000 24.493956 m +9.147122 24.493956 7.709934 24.494541 6.557355 24.404799 c +5.395766 24.314354 4.453906 24.128466 3.602690 23.718542 c +4.322937 22.222933 l +4.911203 22.506227 5.622035 22.666948 6.686217 22.749807 c +7.759411 22.833370 9.121075 22.833956 11.000000 22.833956 c +11.000000 24.493956 l +h +0.830000 12.663956 m +0.830000 14.542881 0.830586 15.904545 0.914148 16.977737 c +0.997008 18.041920 1.157728 18.752752 1.441022 19.341019 c +-0.054586 20.061266 l +-0.464510 19.210049 -0.650399 18.268190 -0.740843 17.106600 c +-0.830586 15.954021 -0.830000 14.516833 -0.830000 12.663956 c +0.830000 12.663956 l +h +3.602690 23.718542 m +2.004527 22.948908 0.715049 21.659428 -0.054586 20.061266 c +1.441022 19.341019 l +2.047490 20.600363 3.063593 21.616465 4.322937 22.222933 c +3.602690 23.718542 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 14.000000 3.169342 cm +0.000000 0.000000 0.000000 scn +2.895337 1.513170 m +2.155802 1.889982 l +2.895337 1.513170 l +h +2.349067 0.966900 m +2.725879 0.227365 l +2.349067 0.966900 l +h +4.396603 9.526595 m +4.019791 10.266130 l +4.396603 9.526595 l +h +3.304063 8.434055 m +2.564527 8.810867 l +3.304063 8.434055 l +h +11.863758 10.481591 m +11.124223 10.858403 l +11.863758 10.481591 l +h +11.317488 9.935321 m +11.694300 9.195786 l +11.317488 9.935321 l +h +11.170000 12.830658 m +11.170000 11.799080 l +12.830000 11.799080 l +12.830000 12.830658 l +11.170000 12.830658 l +h +10.000000 10.629079 m +7.031581 10.629079 l +7.031581 8.969079 l +10.000000 8.969079 l +10.000000 10.629079 l +h +2.201579 5.799079 m +2.201579 2.830659 l +3.861579 2.830659 l +3.861579 5.799079 l +2.201579 5.799079 l +h +1.031579 1.660658 m +0.000000 1.660658 l +0.000000 0.000658 l +1.031579 0.000658 l +1.031579 1.660658 l +h +2.201579 2.830659 m +2.201579 2.466930 2.200933 2.244051 2.187305 2.077250 c +2.180954 1.999516 2.172969 1.952377 2.166202 1.923643 c +2.162982 1.909968 2.160270 1.901502 2.158613 1.896861 c +2.157021 1.892399 2.156040 1.890450 2.155802 1.889982 c +3.634872 1.136358 l +3.772548 1.406561 3.820568 1.682304 3.841792 1.942073 c +3.862224 2.192151 3.861579 2.494322 3.861579 2.830659 c +2.201579 2.830659 l +h +1.031579 0.000658 m +1.367916 0.000658 1.670086 0.000012 1.920165 0.020445 c +2.179933 0.041669 2.455676 0.089689 2.725879 0.227365 c +1.972255 1.706435 l +1.971787 1.706197 1.969838 1.705216 1.965376 1.703624 c +1.960735 1.701967 1.952269 1.699255 1.938594 1.696035 c +1.909860 1.689268 1.862720 1.681283 1.784988 1.674932 c +1.618186 1.661304 1.395307 1.660658 1.031579 1.660658 c +1.031579 0.000658 l +h +2.155802 1.889982 m +2.115535 1.810954 2.051283 1.746702 1.972255 1.706435 c +2.725879 0.227365 l +3.117256 0.426782 3.435456 0.744981 3.634872 1.136358 c +2.155802 1.889982 l +h +7.031581 10.629079 m +6.345211 10.629079 5.780515 10.629725 5.321996 10.592262 c +4.853787 10.554008 4.423688 10.471928 4.019791 10.266130 c +4.773415 8.787060 l +4.904296 8.853747 5.091620 8.907908 5.457173 8.937775 c +5.832415 8.968433 6.317819 8.969079 7.031581 8.969079 c +7.031581 10.629079 l +h +3.861579 5.799079 m +3.861579 6.512841 3.862224 6.998244 3.892883 7.373486 c +3.922750 7.739038 3.976911 7.926362 4.043598 8.057243 c +2.564527 8.810867 l +2.358731 8.406969 2.276650 7.976871 2.238396 7.508663 c +2.200933 7.050144 2.201579 6.485449 2.201579 5.799079 c +3.861579 5.799079 l +h +4.019791 10.266130 m +3.393211 9.946873 2.883785 9.437447 2.564527 8.810867 c +4.043598 8.057243 l +4.203707 8.371473 4.459184 8.626951 4.773415 8.787060 c +4.019791 10.266130 l +h +11.170000 11.799080 m +11.170000 11.435350 11.169354 11.212472 11.155726 11.045670 c +11.149375 10.967937 11.141390 10.920798 11.134623 10.892064 c +11.131403 10.878389 11.128691 10.869923 11.127034 10.865282 c +11.125442 10.860820 11.124461 10.858871 11.124223 10.858403 c +12.603293 10.104778 l +12.740969 10.374982 12.788989 10.650725 12.810213 10.910493 c +12.830646 11.160572 12.830000 11.462742 12.830000 11.799080 c +11.170000 11.799080 l +h +10.000000 8.969079 m +10.336337 8.969079 10.638507 8.968433 10.888586 8.988866 c +11.148354 9.010090 11.424097 9.058110 11.694300 9.195786 c +10.940676 10.674856 l +10.940208 10.674618 10.938259 10.673637 10.933797 10.672045 c +10.929156 10.670388 10.920690 10.667677 10.907015 10.664455 c +10.878281 10.657689 10.831141 10.649704 10.753409 10.643353 c +10.586607 10.629725 10.363729 10.629079 10.000000 10.629079 c +10.000000 8.969079 l +h +11.124223 10.858403 m +11.083956 10.779375 11.019704 10.715123 10.940676 10.674856 c +11.694300 9.195786 l +12.085677 9.395203 12.403876 9.713402 12.603293 10.104778 c +11.124223 10.858403 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 10.000000 16.250000 cm +0.000000 0.000000 0.000000 scn +3.000000 1.750000 m +3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c +0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c +0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c +2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 17.000000 16.250000 cm +0.000000 0.000000 0.000000 scn +3.000000 1.750000 m +3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c +0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c +0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c +2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 11.000000 8.230942 cm +0.000000 0.000000 0.000000 scn +0.664000 4.267058 m +0.388962 4.633775 -0.131283 4.708096 -0.498000 4.433058 c +-0.864717 4.158020 -0.939038 3.637775 -0.664000 3.271058 c +0.664000 4.267058 l +h +4.000000 1.769054 m +3.999999 0.939054 l +4.000000 0.939054 l +4.000000 1.769054 l +h +6.332036 1.389412 m +6.752154 1.572791 6.944070 2.062022 6.760692 2.482140 c +6.577314 2.902259 6.088083 3.094175 5.667964 2.910796 c +6.332036 1.389412 l +h +0.000000 3.769058 m +-0.664000 3.271058 -0.663799 3.270791 -0.663593 3.270516 c +-0.663516 3.270414 -0.663304 3.270131 -0.663150 3.269927 c +-0.662843 3.269519 -0.662512 3.269080 -0.662157 3.268610 c +-0.661448 3.267670 -0.660643 3.266607 -0.659743 3.265423 c +-0.657943 3.263054 -0.655763 3.260200 -0.653203 3.256877 c +-0.648084 3.250230 -0.641445 3.241700 -0.633302 3.231414 c +-0.617020 3.210848 -0.594689 3.183217 -0.566423 3.149538 c +-0.509945 3.082245 -0.429440 2.990409 -0.325813 2.882277 c +-0.119243 2.666726 0.183137 2.382302 0.574317 2.097807 c +1.353481 1.531142 2.521308 0.939057 3.999999 0.939054 c +4.000001 2.599054 l +2.978692 2.599056 2.146519 3.006973 1.550683 3.440309 c +1.254363 3.655814 1.025493 3.871391 0.872688 4.030839 c +0.796627 4.110207 0.740414 4.174622 0.705095 4.216704 c +0.687462 4.237712 0.675126 4.253050 0.668214 4.261781 c +0.664761 4.266143 0.662671 4.268843 0.661961 4.269765 c +0.661607 4.270226 0.661598 4.270240 0.661937 4.269794 c +0.662106 4.269571 0.662363 4.269233 0.662706 4.268778 c +0.662878 4.268550 0.663072 4.268293 0.663288 4.268007 c +0.663395 4.267863 0.663574 4.267626 0.663627 4.267555 c +0.663811 4.267310 0.664000 4.267058 0.000000 3.769058 c +h +4.000000 0.939054 m +4.844985 0.939054 5.627935 1.082078 6.332036 1.389412 c +5.667964 2.910796 l +5.208086 2.710063 4.657703 2.599054 4.000000 2.599054 c +4.000000 0.939054 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 10900 +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 +0000010990 00000 n +0000011014 00000 n +0000011187 00000 n +0000011261 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +11320 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 5fd0ef4b1a..9ff570f2e4 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -917,8 +917,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)) @@ -1494,13 +1494,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G 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 + }, sendSticker: { [weak self] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect 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,7 +1517,7 @@ 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 } @@ -1545,7 +1545,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,12 +1562,14 @@ 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 { + } } @@ -1590,7 +1592,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }, sendGif: { [weak self] fileReference, sourceNode, 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(sourceNode.view, sourceRect) return false } @@ -1632,7 +1634,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(sourceNode.view, sourceRect) return false } @@ -2947,7 +2949,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 { @@ -3288,8 +3290,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)) @@ -6128,7 +6130,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 } @@ -7197,7 +7199,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 } @@ -7581,9 +7583,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } } - }, sendSticker: { [weak self] file, clearInput, sourceNode, sourceRect in + }, sendSticker: { [weak self] file, clearInput, sourceView, sourceRect 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) ?? false } else { return false } @@ -8240,11 +8242,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 { @@ -8559,6 +8561,28 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return $0.updatedShowWebView(f($0.showWebView)) }) } + }, insertText: { [weak self] text in + guard let strongSelf = self else { + return + } + if !strongSelf.chatDisplayNode.isTextInputPanelActive { + return + } + guard let textInputPanelNode = strongSelf.chatDisplayNode.textInputPanelNode else { + return + } + textInputPanelNode.insertText(string: text) + }, 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())) @@ -10759,8 +10783,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)) @@ -11364,8 +11388,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 +11486,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)) @@ -11672,8 +11696,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 +11793,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 +11840,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 +11897,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)) @@ -12723,8 +12747,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)) @@ -12944,8 +12968,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 @@ -13131,7 +13155,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 } @@ -14821,8 +14845,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) ?? false }, requestMessageActionUrlAuth: { [weak self] subject in if case let .url(url) = subject { self?.controllerInteraction?.requestMessageActionUrlAuth(url, subject) diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index d950b8235e..1fac0dc958 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -73,7 +73,7 @@ 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 sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect) -> Bool let sendGif: (FileMediaReference, ASDisplayNode, CGRect, Bool, Bool) -> Bool let sendBotContextResultAsGif: (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect, Bool) -> Bool let requestMessageActionCallback: (MessageId, MemoryBuffer?, Bool, Bool) -> Void @@ -176,7 +176,7 @@ 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, + sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect) -> Bool, sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect, Bool, Bool) -> Bool, sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect, Bool) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool, Bool) -> Void, diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 4b963f0286..81c407e371 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -83,7 +83,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let backgroundNode: WallpaperBackgroundNode let historyNode: ChatHistoryListNode - //let historyScrollingArea: SparseDiscreteScrollingArea var blurredHistoryNode: ASImageNode? let historyNodeContainer: ASDisplayNode let loadingNode: ChatLoadingNode @@ -100,7 +99,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let inputPanelContainerNode: SparseNode private let inputPanelBackgroundNode: NavigationBackgroundNode + private var intrinsicInputPanelBackgroundNodeSize: CGSize? private let inputPanelBackgroundSeparatorNode: ASDisplayNode + private let inputPanelBottomBackgroundSeparatorNode: ASDisplayNode private var plainInputSeparatorAlpha: CGFloat? private var usePlainInputSeparator: Bool @@ -122,7 +123,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 @@ -378,6 +384,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 @@ -499,6 +509,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.addSubnode(self.inputPanelContainerNode) self.inputPanelContainerNode.addSubnode(self.inputPanelBackgroundNode) self.inputPanelContainerNode.addSubnode(self.inputPanelBackgroundSeparatorNode) + self.inputPanelContainerNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode) self.addSubnode(self.inputContextPanelContainer) @@ -553,12 +564,21 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.textInputPanelNode?.updateActivity = { [weak self] in self?.updateTypingActivity(true) } + + 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() { @@ -886,14 +906,17 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let maximumInputNodeHeight = layout.size.height - max(navigationBarHeight + (titleAccessoryPanelBackgroundHeight ?? 0.0), layout.safeInsets.top) - inputPanelNodeBaseHeight var dismissedInputNode: ChatInputNode? + 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 let inputNode = 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() + }) { + /*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 { self.inputMediaNode = inputMediaNode inputMediaNode.requestDisableStickerAnimations = { [weak self] disabled in @@ -901,20 +924,34 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } if self.inputNode != inputNode { + inputNode.topBackgroundExtensionUpdated = { [weak self] transition in + self?.updateInputPanelBackgroundExtension(transition: transition) + } + dismissedInputNode = self.inputNode + 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) - } else { - self.inputPanelContainerNode.insertSubnode(inputNode, aboveSubnode: self.inputPanelBackgroundNode) + /*if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: inputPanelNode) + } else {*/ + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) + //} + + if let externalTopPanelContainer = inputNode.externalTopPanelContainer { + if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { + self.inputPanelContainerNode.view.insertSubview(externalTopPanelContainer, belowSubview: inputPanelNode.view) + } else { + self.inputPanelContainerNode.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) } else if let inputNode = self.inputNode { dismissedInputNode = inputNode + dismissedInputNodeExternalTopPanelContainer = inputNode.externalTopPanelContainer self.inputNode = nil } @@ -1357,7 +1394,16 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) + + 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 + } + self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: transition) + transition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBackgroundNode.frame.maxY + inputPanelBackgroundExtension), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) + 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) @@ -1437,8 +1483,16 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { adjustedForPreviousInputHeightFrame.origin.y += heightDifference inputNode.frame = adjustedForPreviousInputHeightFrame transition.updateFrame(node: inputNode, frame: inputNodeFrame) + + if let externalTopPanelContainer = inputNode.externalTopPanelContainer { + externalTopPanelContainer.frame = CGRect(origin: adjustedForPreviousInputHeightFrame.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))) + } } } @@ -1628,6 +1682,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 +1760,20 @@ 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.inputPanelBackgroundNode.frame.maxY + extensionValue), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) + } + private func notifyTransitionCompletionListeners(transition: ContainedViewLayoutTransition) { if !self.onLayoutCompletions.isEmpty { let onLayoutCompletions = self.onLayoutCompletions @@ -1700,14 +1786,28 @@ 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 let emptyInputView = UIView() + private func chatPresentationInterfaceStateInputView(_ state: ChatPresentationInterfaceState) -> UIView? { + switch state.inputMode { + case .text: + return nil + case .media: + return self.emptyInputView + default: + return nil } } @@ -1730,6 +1830,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.historyNode.verticalScrollIndicatorColor = UIColor(white: 0.5, alpha: 0.8) let updatedInputFocus = self.chatPresentationInterfaceStateRequiresInputFocus(self.chatPresentationInterfaceState) != self.chatPresentationInterfaceStateRequiresInputFocus(chatPresentationInterfaceState) + let updateInputTextState = self.chatPresentationInterfaceState.interfaceState.effectiveInputState != chatPresentationInterfaceState.interfaceState.effectiveInputState self.chatPresentationInterfaceState = chatPresentationInterfaceState @@ -1746,6 +1847,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,6 +1942,16 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.navigationBar?.setContentNode(nil, animated: transitionIsAnimated) } + if let textView = self.textInputPanelNode?.textInputNode?.textView { + let updatedInputView = self.chatPresentationInterfaceStateInputView(chatPresentationInterfaceState) + if textView.inputView !== updatedInputView { + textView.inputView = updatedInputView + if textView.isFirstResponder { + textView.reloadInputViews() + } + } + } + if updatedInputFocus { if !self.ignoreUpdateHeight { self.scheduleLayoutTransitionRequest(layoutTransition) @@ -1963,8 +2075,30 @@ 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 _ = peerId + + let inputNode = ChatEntityKeyboardInputNode(context: self.context, currentInputData: inputMediaNodeData, updatedInputData: self.inputMediaNodeDataPromise.get()) + + 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)) + } + + 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 { @@ -1989,9 +2123,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) } - - self.textInputPanelNode?.loadTextInputNodeIfNeeded() } + + self.textInputPanelNode?.loadTextInputNodeIfNeeded() } func currentInputPanelFrame() -> CGRect? { @@ -2376,14 +2510,20 @@ 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 { + self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in + return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) }) } } @@ -2409,7 +2549,7 @@ 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 } diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index 5b87ffd1fe..d14c8a99a1 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) } 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) } 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..3832a6764c --- /dev/null +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -0,0 +1,217 @@ +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 + +final class ChatEntityKeyboardInputNode: ChatInputNode { + struct InputData: Equatable { + let emoji: EmojiPagerContentComponent + let stickers: EmojiPagerContentComponent + + init( + emoji: EmojiPagerContentComponent, + stickers: EmojiPagerContentComponent + ) { + self.emoji = emoji + self.stickers = stickers + } + } + + static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction) -> Signal { + let emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( + performItemAction: { [weak interfaceInteraction] item, _, _ in + guard let interfaceInteraction = interfaceInteraction else { + return + } + interfaceInteraction.insertText(item.emoji) + }, + deleteBackwards: { [weak interfaceInteraction] in + guard let interfaceInteraction = interfaceInteraction else { + return + } + interfaceInteraction.backwardsDeleteText() + } + ) + let stickerInputInteraction = EmojiPagerContentComponent.InputInteraction( + performItemAction: { [weak interfaceInteraction] item, view, rect in + guard let interfaceInteraction = interfaceInteraction else { + return + } + let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, view, rect) + }, + deleteBackwards: { [weak interfaceInteraction] in + guard let interfaceInteraction = interfaceInteraction else { + return + } + interfaceInteraction.backwardsDeleteText() + } + ) + + let animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { + return TempBox.shared.tempFile(fileName: "file").path + }) + let animationRenderer = MultiAnimationRendererImpl() + + let emojiItems: Signal = context.engine.stickers.loadedStickerPack(reference: .animatedEmoji, forceActualized: false) + |> map { animatedEmoji -> EmojiPagerContentComponent in + var emojiItems: [EmojiPagerContentComponent.Item] = [] + + switch animatedEmoji { + case let .result(_, items, _): + for item in items { + if let emoji = item.getStringRepresentationsOfIndexKeys().first { + let strippedEmoji = emoji.basicEmoji.0.strippedEmoji + emojiItems.append(EmojiPagerContentComponent.Item( + emoji: strippedEmoji, + file: item.file + )) + } + } + default: + break + } + + var itemGroups: [EmojiPagerContentComponent.ItemGroup] = [] + itemGroups.append(EmojiPagerContentComponent.ItemGroup( + id: "all", + title: nil, + items: emojiItems + )) + return EmojiPagerContentComponent( + context: context, + animationCache: animationCache, + animationRenderer: animationRenderer, + inputInteraction: emojiInputInteraction, + itemGroups: itemGroups, + itemLayoutType: .compact + ) + } + + let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers] + let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] + let stickerItems: Signal = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000) + |> map { view -> EmojiPagerContentComponent in + struct ItemGroup { + var id: ItemCollectionId + var items: [EmojiPagerContentComponent.Item] + } + var itemGroups: [ItemGroup] = [] + var itemGroupIndexById: [AnyHashable: Int] = [:] + + for entry in view.entries { + guard let item = entry.item as? StickerPackItem else { + continue + } + if !item.file.isAnimatedSticker { + continue + } + let resultItem = EmojiPagerContentComponent.Item( + emoji: "", + file: item.file + ) + let groupId = entry.index.collectionId + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + } + } + + return EmojiPagerContentComponent( + context: context, + animationCache: animationCache, + animationRenderer: animationRenderer, + inputInteraction: stickerInputInteraction, + itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in + var title: String? + for (id, info, _) in view.collectionInfos { + if id == group.id, let info = info as? StickerPackCollectionInfo { + title = info.title.uppercased() + break + } + } + + return EmojiPagerContentComponent.ItemGroup(id: group.id, title: title, items: group.items) + }, + itemLayoutType: .detailed + ) + } + + return combineLatest(queue: .mainQueue(), + emojiItems, + stickerItems + ) + |> map { emoji, stickers -> InputData in + return InputData( + emoji: emoji, + stickers: stickers + ) + } + } + + private let entityKeyboardView: ComponentHostView + + private var currentInputData: InputData + private var inputDataDisposable: Disposable? + + init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal) { + self.currentInputData = currentInputData + self.entityKeyboardView = ComponentHostView() + + super.init() + + self.view.addSubview(self.entityKeyboardView) + + self.externalTopPanelContainer = SparseContainerView() + + self.inputDataDisposable = (updatedInputData + |> deliverOnMainQueue).start(next: { [weak self] inputData in + guard let strongSelf = self else { + return + } + strongSelf.currentInputData = inputData + }) + } + + deinit { + self.inputDataDisposable?.dispose() + } + + 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) { + let entityKeyboardSize = self.entityKeyboardView.update( + transition: Transition(transition), + component: AnyComponent(EntityKeyboardComponent( + theme: interfaceState.theme, + bottomInset: bottomInset, + emojiContent: self.currentInputData.emoji, + stickerContent: self.currentInputData.stickers, + externalTopPanelContainer: self.externalTopPanelContainer, + topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in + guard let strongSelf = self else { + return + } + if strongSelf.topBackgroundExtension != topPanelExtension { + strongSelf.topBackgroundExtension = topPanelExtension + strongSelf.topBackgroundExtensionUpdated?(transition.containedViewLayoutTransition) + } + } + )), + environment: {}, + containerSize: CGSize(width: width, height: standardInputHeight) + ) + transition.updateFrame(view: self.entityKeyboardView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: entityKeyboardSize)) + + return (standardInputHeight, 0.0) + } +} diff --git a/submodules/TelegramUI/Sources/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index 0b955aecc1..ca1ebffaab 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -11,6 +11,11 @@ class ChatInputNode: ASDisplayNode { return .single(Void()) } + var externalTopPanelContainer: UIView? + + var topBackgroundExtension: CGFloat = 0.0 + var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> 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) { return (0.0, 0.0) } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index 2e95f80d98..68d107097c 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift @@ -317,13 +317,9 @@ 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)) - } - #endif + if isTextEmpty, let message = chatPresentationInterfaceState.keyboardButtonsMessage, let _ = message.visibleButtonKeyboardMarkup, chatPresentationInterfaceState.interfaceState.messageActionsState.dismissedButtonKeyboardMessageId != message.id { accessoryItems.append(.inputButtons) } 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/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index bb3373b2b6..40faa41d68 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -1579,9 +1579,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) } 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) } } f(.default) @@ -1593,9 +1593,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) } 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) } } f(.default) @@ -1731,9 +1731,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) } 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) } } f(.default) @@ -1745,9 +1745,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) } 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) } } f(.default) diff --git a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift index f06f403ee9..b18d419cf6 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift @@ -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) self.imageNode.layer.animateAlpha(from: 0.5, to: 1.0, duration: 1.0) } } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift b/submodules/TelegramUI/Sources/ChatRecentActionsController.swift index eaa4b84307..ba675ff969 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsController.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsController.swift @@ -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/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 06ddecf35f..c4798cd366 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -177,7 +177,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 +194,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 += accessoryButtonsWidth + + return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: right) } private var currentTextInputBackgroundImage: (UIColor, UIColor, CGFloat, UIImage)? @@ -667,7 +671,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { 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 { return UIView() @@ -675,7 +679,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { return EmojiTextAttachmentView(context: context, file: file, cache: presentationContext.animationCache, renderer: presentationContext.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12)) } - }*/ + } } required init?(coder aDecoder: NSCoder) { @@ -725,26 +729,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() @@ -1647,7 +1651,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) @@ -1717,7 +1721,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.slowmodePlaceholderNode?.isHidden = true } - var nextButtonTopRight = CGPoint(x: width - rightInset - textFieldInsets.right - accessoryButtonInset, y: minimalHeight - textFieldInsets.bottom - minimalInputHeight) + var nextButtonTopRight = CGPoint(x: width - rightInset - textFieldInsets.right - accessoryButtonInset, y: panelHeight - textFieldInsets.bottom - minimalInputHeight) for (_, button) in self.accessoryItemButtons.reversed() { let buttonSize = CGSize(width: button.buttonWidth, height: minimalInputHeight) button.updateLayout(size: buttonSize) @@ -2320,9 +2324,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 +2348,20 @@ 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, .media: + self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId { _ in + return (.none, nil) + } + default: + break + } } } } @@ -2698,6 +2727,20 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.textInputNode?.becomeFirstResponder() } + func insertText(string: String) { + guard let textInputNode = self.textInputNode else { + return + } + textInputNode.textView.insertText(string) + } + + func backwardsDeleteText() { + guard let textInputNode = self.textInputNode else { + return + } + textInputNode.textView.deleteBackward() + } + @objc func expandButtonPressed() { self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in if case let .media(mode, expanded, focused) = state.inputMode { diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index dc168430ca..155e383412 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,7 +106,7 @@ 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 @@ -1306,7 +1306,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 +1322,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 +1362,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/FeaturedStickersScreen.swift b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift index 39986aa3ae..2c5e72a1c4 100644 --- a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift +++ b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift @@ -192,7 +192,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 +222,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 @@ -485,9 +485,9 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { .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) @@ -576,7 +576,7 @@ private final class FeaturedStickersScreenNode: ViewControllerTracingNode { 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) })), @@ -789,7 +789,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 +805,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 +1034,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 +1080,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 +1115,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,9 +1175,9 @@ 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) diff --git a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift index 23a4da53d9..ce97e1b83e 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -162,9 +162,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) ?? false } else { return false } 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..1d99c75e84 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -180,7 +180,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { .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) })), .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) diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index 74f9b3eca9..ef2e3bd426 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -45,7 +45,7 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie var previewedStickerItem: StickerPackItem? var updateBackgroundOffset: ((CGFloat, Bool, ContainedViewLayoutTransition) -> Void)? - var sendSticker: ((FileMediaReference, ASDisplayNode, CGRect) -> Void)? + var sendSticker: ((FileMediaReference, UIView, CGRect) -> Void)? var getControllerInteraction: (() -> ChatControllerInteraction?)? @@ -111,9 +111,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) } 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) } } f(.default) @@ -125,9 +125,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) } 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) } } f(.default) @@ -434,8 +434,8 @@ private final class InlineReactionSearchStickersNode: ASDisplayNode, UIScrollVie 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) + }, sendSticker: { [weak self] file, view, rect in + self?.sendSticker?(file, view, rect) } ) itemNode = item.node(layout: GridNodeLayout( diff --git a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift index 6ae0117529..a5bd2aa3c8 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) @@ -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/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index 490c7bc021..cd1c1377ac 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 diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 7b34ad0bcb..20756b514b 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -359,6 +359,8 @@ final class PeerInfoSelectionPanelNode: ASDisplayNode { displayCopyProtectionTip(node, save) }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) @@ -3357,8 +3359,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)) @@ -6051,10 +6053,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)) diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index cb19f498c2..b88389adb5 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -349,6 +349,8 @@ final class PeerSelectionControllerNode: ASDisplayNode { }, displayCopyProtectionTip: { _, _ in }, openWebView: { _, _, _, _ in }, updateShowWebView: { _ in + }, insertText: { _ in + }, backwardsDeleteText: { }, chatController: { return nil }, statuses: nil) diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index ec89f0bb4b..0771a98da8 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1201,7 +1201,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) } diff --git a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift index 3f735b3a4c..581ac2be30 100644 --- a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift @@ -19,10 +19,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 +100,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() @@ -319,9 +319,9 @@ 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) } }, getItemIsPreviewed: { item in return inputNodeInteraction.previewedStickerPackItem == .pack(item) diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift index a0055a4545..e474a5c6ee 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) break } } diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index b31262461c..8f23e7f235 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -136,7 +136,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { .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) })), .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) From 0f1b382265d42abeb5899db975252aa35142eedf Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 21 Jun 2022 21:47:01 +0100 Subject: [PATCH 002/113] [Temp] Input panel progress --- .../Telegram-iOS/en.lproj/Localizable.strings | 1 + .../Sources/VideoStickerFrameSource.swift | 4 + .../Sources/AttachmentPanel.swift | 2 +- .../ChatPanelInterfaceInteraction.swift | 6 +- .../Sources/PagerComponent.swift | 67 +- submodules/Display/Source/UIKitUtils.swift | 52 ++ .../Sources/SampleBufferPool.swift | 1 - .../SoftwareVideoLayerFrameManager.swift | 19 +- .../Components/EntityKeyboard/BUILD | 5 + .../Sources/EmojiPagerContentComponent.swift | 119 ++-- .../Sources/EntityKeyboard.swift | 84 ++- .../EntityKeyboardBottomPanelComponent.swift | 33 +- .../EntityKeyboardTopPanelComponent.swift | 8 +- .../Sources/GifPagerContentComponent.swift | 585 ++++++++++++++++++ .../Components/MultiVideoRenderer/BUILD | 20 + .../Sources/MultiVideoRenderer.swift | 399 ++++++++++++ .../Components/VideoAnimationCache/BUILD | 21 + .../Sources/VideoAnimationCache.swift | 35 ++ .../TelegramUI/Sources/ChatController.swift | 33 +- .../Sources/ChatControllerInteraction.swift | 8 +- .../Sources/ChatControllerNode.swift | 2 +- .../TelegramUI/Sources/ChatEmptyNode.swift | 4 +- .../Sources/ChatEntityKeyboardInputNode.swift | 231 ++++++- .../Sources/ChatMediaInputGifPane.swift | 2 +- .../Sources/ChatMediaInputNode.swift | 32 +- .../ChatMediaInputStickerGridItem.swift | 2 +- .../Sources/ChatMediaInputTrendingPane.swift | 2 +- .../ChatMessageAnimatedStickerItemNode.swift | 21 +- .../Sources/ChatMessageStickerItemNode.swift | 16 +- .../Sources/ChatMessageTransitionNode.swift | 58 +- .../Sources/ChatRecentActionsController.swift | 2 +- .../ChatRecentActionsControllerNode.swift | 2 +- .../Sources/DrawingStickersScreen.swift | 6 +- .../Sources/GifPaneSearchContentNode.swift | 2 +- ...textResultsChatInputContextPanelNode.swift | 2 +- ...rizontalStickersChatContextPanelNode.swift | 6 +- .../Sources/InlineReactionSearchPanel.swift | 12 +- .../OverlayAudioPlayerControllerNode.swift | 2 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 4 +- .../Sources/PeerSelectionControllerNode.swift | 2 +- .../Sources/SharedAccountContext.swift | 2 +- .../StickerPaneSearchContentNode.swift | 4 +- .../StickersChatInputContextPanelItem.swift | 2 +- .../StickersChatInputContextPanelNode.swift | 4 +- 44 files changed, 1728 insertions(+), 196 deletions(-) create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift create mode 100644 submodules/TelegramUI/Components/MultiVideoRenderer/BUILD create mode 100644 submodules/TelegramUI/Components/MultiVideoRenderer/Sources/MultiVideoRenderer.swift create mode 100644 submodules/TelegramUI/Components/VideoAnimationCache/BUILD create mode 100644 submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 77a7b3d94f..6d63268b5b 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -106,6 +106,7 @@ "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$@"; "PUSH_CHANNEL_MESSAGE_TEXT" = "%1$@|%2$@"; "PUSH_CHANNEL_MESSAGE_NOTEXT" = "%1$@|posted a message"; diff --git a/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift b/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift index 166f7cdf80..2038bbed6c 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?) -> AnimatedStickerFrameSource? { + return VideoStickerDirectFrameSource(queue: queue, path: path, width: width, height: height, cachePathPrefix: cachePathPrefix) +} + final class VideoStickerDirectFrameSource: AnimatedStickerFrameSource { private let queue: Queue private let path: String diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 011a9cb6af..0cb84a5b20 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -593,7 +593,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _ in + }, sendSticker: { _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index 13e206aff6..cae532aea0 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -98,7 +98,7 @@ public final class ChatPanelInterfaceInteraction { public let displayVideoUnmuteTip: (CGPoint?) -> Void public let switchMediaRecordingMode: () -> Void public let setupMessageAutoremoveTimeout: () -> Void - public let sendSticker: (FileMediaReference, Bool, UIView, 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 @@ -194,7 +194,7 @@ public final class ChatPanelInterfaceInteraction { displayVideoUnmuteTip: @escaping (CGPoint?) -> Void, switchMediaRecordingMode: @escaping () -> Void, setupMessageAutoremoveTimeout: @escaping () -> Void, - sendSticker: @escaping (FileMediaReference, Bool, UIView, CGRect) -> Bool, + sendSticker: @escaping (FileMediaReference, Bool, UIView, CGRect, CALayer?) -> Bool, unblockPeer: @escaping () -> Void, pinMessage: @escaping (MessageId, ContextControllerProtocol?) -> Void, unpinMessage: @escaping (MessageId, Bool, ContextControllerProtocol?) -> Void, @@ -391,7 +391,7 @@ public final class ChatPanelInterfaceInteraction { }, displayVideoUnmuteTip: { _ in }, switchMediaRecordingMode: { }, setupMessageAutoremoveTimeout: { - }, sendSticker: { _, _, _, _ in + }, sendSticker: { _, _, _, _, _ in return false }, unblockPeer: { }, pinMessage: { _, _ in diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index daa4be7312..12b311e547 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -46,19 +46,22 @@ public final class PagerComponentPanelEnvironment: Equatable { public let contentIcons: [AnyComponentWithIdentity] public let contentAccessoryRightButtons: [AnyComponentWithIdentity] public let activeContentId: AnyHashable? + public let navigateToContentId: (AnyHashable) -> Void init( contentOffset: CGFloat, contentTopPanels: [AnyComponentWithIdentity], contentIcons: [AnyComponentWithIdentity], contentAccessoryRightButtons: [AnyComponentWithIdentity], - activeContentId: AnyHashable? + activeContentId: AnyHashable?, + navigateToContentId: @escaping (AnyHashable) -> Void ) { self.contentOffset = contentOffset self.contentTopPanels = contentTopPanels self.contentIcons = contentIcons self.contentAccessoryRightButtons = contentAccessoryRightButtons self.activeContentId = activeContentId + self.navigateToContentId = navigateToContentId } public static func ==(lhs: PagerComponentPanelEnvironment, rhs: PagerComponentPanelEnvironment) -> Bool { @@ -253,6 +256,16 @@ public final class PagerComponent: Component { self.component = component self.state = state + let navigateToContentId: (AnyHashable) -> Void = { [weak self] id in + guard let strongSelf = self else { + return + } + if strongSelf.centralId != id { + strongSelf.centralId = id + 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 }) { @@ -309,7 +322,8 @@ public final class PagerComponent: Component { contentTopPanels: component.contentTopPanels, contentIcons: [], contentAccessoryRightButtons: [], - activeContentId: centralId + activeContentId: centralId, + navigateToContentId: navigateToContentId ) }, containerSize: availableSize @@ -356,7 +370,8 @@ public final class PagerComponent: Component { contentTopPanels: [], contentIcons: component.contentIcons, contentAccessoryRightButtons: component.contentAccessoryRightButtons, - activeContentId: centralId + activeContentId: centralId, + navigateToContentId: navigateToContentId ) }, containerSize: availableSize @@ -404,15 +419,27 @@ public final class PagerComponent: Component { 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 - var contentFrame = CGRect(origin: CGPoint(x: contentSize.width * CGFloat(indexOffset), y: 0.0), size: contentSize) + 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(contentFrame) + let isInBounds = CGRect(origin: CGPoint(), size: availableSize).intersects(checkingContentFrame) var isPartOfTransition = false if case .none = transition.animation { @@ -462,7 +489,35 @@ public final class PagerComponent: Component { ) if wasAdded { - contentView.view.frame = contentFrame + 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 { diff --git a/submodules/Display/Source/UIKitUtils.swift b/submodules/Display/Source/UIKitUtils.swift index 2b6ee6a68e..3592dc0062 100644 --- a/submodules/Display/Source/UIKitUtils.swift +++ b/submodules/Display/Source/UIKitUtils.swift @@ -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/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..fd3ab89d89 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() } @@ -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/TelegramUI/Components/EntityKeyboard/BUILD b/submodules/TelegramUI/Components/EntityKeyboard/BUILD index 254b799425..5947ec2a2e 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/BUILD +++ b/submodules/TelegramUI/Components/EntityKeyboard/BUILD @@ -26,8 +26,13 @@ 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/TelegramUI/Components/MultiVideoRenderer:MultiVideoRenderer", + "//submodules/SoftwareVideo:SoftwareVideo", "//submodules/ShimmerEffect:ShimmerEffect", + "//submodules/PhotoResources:PhotoResources", + "//submodules/StickerResources:StickerResources", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 0c684fa098..f8ed135071 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -10,25 +10,30 @@ import MultiAnimationRenderer import AnimationCache import AccountContext import LottieAnimationCache +import VideoAnimationCache import AnimatedStickerNode import TelegramAnimatedStickerNode import SwiftSignalKit import ShimmerEffect import PagerComponent +import StickerResources public final class EmojiPagerContentComponent: Component { public typealias EnvironmentType = (EntityKeyboardChildEnvironment, PagerComponentChildEnvironment) public final class InputInteraction { - public let performItemAction: (Item, UIView, CGRect) -> Void + public let performItemAction: (Item, UIView, CGRect, CALayer) -> Void public let deleteBackwards: () -> Void + public let openStickerSettings: () -> Void public init( - performItemAction: @escaping (Item, UIView, CGRect) -> Void, - deleteBackwards: @escaping () -> Void + performItemAction: @escaping (Item, UIView, CGRect, CALayer) -> Void, + deleteBackwards: @escaping () -> Void, + openStickerSettings: @escaping () -> Void ) { self.performItemAction = performItemAction self.deleteBackwards = deleteBackwards + self.openStickerSettings = openStickerSettings } } @@ -251,6 +256,11 @@ public final class EmojiPagerContentComponent: Component { } final class ItemLayer: MultiAnimationRenderTarget { + struct Key: Hashable { + var groupId: AnyHashable + var fileId: MediaId + } + let item: Item private let file: TelegramMediaFile @@ -290,38 +300,60 @@ public final class EmojiPagerContentComponent: Component { super.init() - if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { - self.displayPlaceholder = true + if file.isAnimatedSticker || file.isVideoSticker { + if attemptSynchronousLoad { + if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { + self.displayPlaceholder = true + + if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: self.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, size: pixelSize, fetch: { size, writer in + let source = AnimatedStickerResourceSource(account: context.account, resource: file.resource, fitzModifier: nil, isVideo: false) - if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: self.size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor) { - self.contents = image.cgImage + let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in + guard let result = result else { + return + } + + if file.isVideoSticker { + 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: stickerPackFileReference(file), resource: file.resource).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() } - } - } - - self.disposable = renderer.add(groupId: groupId, target: self, 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 - } - - 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 = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)).start() - - return ActionDisposable { - dataDisposable.dispose() - fetchDisposable.dispose() - } - }) + } else if let dimensions = file.dimensions { + let isSmall: Bool = false + self.disposable = (chatMessageSticker(account: context.account, file: file, small: isSmall, synchronousLoad: attemptSynchronousLoad)).start(next: { [weak self] resultTransform in + let boundingSize = CGSize(width: 93.0, height: 93.0) + let imageSize = dimensions.cgSize.aspectFilled(boundingSize) + + if let image = resultTransform(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .fill(.clear)))?.generateImage() { + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + + strongSelf.contents = image.cgImage + } + } + }) + } } override public init(layer: Any) { @@ -381,7 +413,7 @@ public final class EmojiPagerContentComponent: Component { private let scrollView: UIScrollView - private var visibleItemLayers: [MediaId: ItemLayer] = [:] + private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:] private var visibleGroupHeaders: [AnyHashable: ComponentHostView] = [:] private var ignoreScrolling: Bool = false @@ -402,7 +434,7 @@ public final class EmojiPagerContentComponent: Component { if #available(iOS 13.0, *) { self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false } - self.scrollView.showsVerticalScrollIndicator = false + self.scrollView.showsVerticalScrollIndicator = true self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.delegate = self self.addSubview(self.scrollView) @@ -416,18 +448,18 @@ public final class EmojiPagerContentComponent: Component { @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[item.file.fileId] { - component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemView.frame, to: self)) + if let component = self.component, let (item, itemKey) = self.item(atPoint: recognizer.location(in: self)), let itemLayer = self.visibleItemLayers[itemKey] { + component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) } } } - private func item(atPoint point: CGPoint) -> Item? { + private func item(atPoint point: CGPoint) -> (Item, ItemLayer.Key)? { let localPoint = self.convert(point, to: self.scrollView) - for (_, itemLayer) in self.visibleItemLayers { + for (key, itemLayer) in self.visibleItemLayers { if itemLayer.frame.contains(localPoint) { - return itemLayer.item + return (itemLayer.item, key) } } @@ -519,7 +551,7 @@ public final class EmojiPagerContentComponent: Component { return } - var validIds = Set() + var validIds = Set() var validGroupHeaderIds = Set() for groupItems in itemLayout.visibleItems(for: self.scrollView.bounds) { @@ -549,7 +581,7 @@ public final class EmojiPagerContentComponent: Component { for index in groupItems.groupItems.lowerBound ..< groupItems.groupItems.upperBound { let item = itemGroup.items[index] - let itemId = item.file.fileId + let itemId = ItemLayer.Key(groupId: itemGroup.id, fileId: item.file.fileId) validIds.insert(itemId) let itemLayer: ItemLayer @@ -566,7 +598,7 @@ public final class EmojiPagerContentComponent: Component { } } - var removedIds: [MediaId] = [] + var removedIds: [ItemLayer.Key] = [] for (id, itemLayer) in self.visibleItemLayers { if !validIds.contains(id) { removedIds.append(id) @@ -612,6 +644,9 @@ public final class EmojiPagerContentComponent: Component { if self.scrollView.contentSize != itemLayout.contentSize { self.scrollView.contentSize = itemLayout.contentSize } + if self.scrollView.scrollIndicatorInsets != pagerEnvironment.containerInsets { + self.scrollView.scrollIndicatorInsets = pagerEnvironment.containerInsets + } self.previousScrollingOffset = self.scrollView.contentOffset.y self.ignoreScrolling = false diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index ae928d87ee..3bc7213fdd 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -30,6 +30,7 @@ public final class EntityKeyboardComponent: Component { public let bottomInset: CGFloat public let emojiContent: EmojiPagerContentComponent public let stickerContent: EmojiPagerContentComponent + public let gifContent: GifPagerContentComponent public let externalTopPanelContainer: UIView? public let topPanelExtensionUpdated: (CGFloat, Transition) -> Void @@ -38,6 +39,7 @@ public final class EntityKeyboardComponent: Component { bottomInset: CGFloat, emojiContent: EmojiPagerContentComponent, stickerContent: EmojiPagerContentComponent, + gifContent: GifPagerContentComponent, externalTopPanelContainer: UIView?, topPanelExtensionUpdated: @escaping (CGFloat, Transition) -> Void ) { @@ -45,6 +47,7 @@ public final class EntityKeyboardComponent: Component { self.bottomInset = bottomInset self.emojiContent = emojiContent self.stickerContent = stickerContent + self.gifContent = gifContent self.externalTopPanelContainer = externalTopPanelContainer self.topPanelExtensionUpdated = topPanelExtensionUpdated } @@ -62,6 +65,9 @@ public final class EntityKeyboardComponent: Component { if lhs.stickerContent != rhs.stickerContent { return false } + if lhs.gifContent != rhs.gifContent { + return false + } if lhs.externalTopPanelContainer != rhs.externalTopPanelContainer { return false } @@ -94,24 +100,78 @@ public final class EntityKeyboardComponent: Component { var contentIcons: [AnyComponentWithIdentity] = [] var contentAccessoryRightButtons: [AnyComponentWithIdentity] = [] - var topStickertems: [EntityKeyboardTopPanelComponent.Item] = [] + contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(component.gifContent))) + var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: "recent", + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/RecentTabIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: CGSize(width: 30.0, height: 30.0)) + ) + )) + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: "trending", + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/TrendingGifs", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: CGSize(width: 30.0, height: 30.0)) + ) + )) + contentTopPanels.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(EntityKeyboardTopPanelComponent( + theme: component.theme, + items: topGifItems + )))) + contentIcons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputGifsIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )))) + /*contentAccessoryRightButtons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputSettingsIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )), + action: { + } + ).minSize(CGSize(width: 38.0, height: 38.0)))))*/ + + var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] for itemGroup in component.stickerContent.itemGroups { - if !itemGroup.items.isEmpty { - topStickertems.append(EntityKeyboardTopPanelComponent.Item( - id: AnyHashable(itemGroup.items[0].file.fileId), - content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( - context: component.stickerContent.context, - file: itemGroup.items[0].file, - animationCache: component.stickerContent.animationCache, - animationRenderer: component.stickerContent.animationRenderer + if let id = itemGroup.id.base as? String { + let iconMapping: [String: String] = [ + "recent": "Chat/Input/Media/RecentTabIcon", + "premium": "Chat/Input/Media/PremiumIcon" + ] + if let iconName = iconMapping[id] { + topStickerItems.append(EntityKeyboardTopPanelComponent.Item( + id: id, + content: AnyComponent(BundleIconComponent( + name: iconName, + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: CGSize(width: 30.0, height: 30.0)) + ) )) - )) + } + } else { + if !itemGroup.items.isEmpty { + topStickerItems.append(EntityKeyboardTopPanelComponent.Item( + id: AnyHashable(itemGroup.items[0].file.fileId), + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.stickerContent.context, + file: itemGroup.items[0].file, + animationCache: component.stickerContent.animationCache, + animationRenderer: component.stickerContent.animationRenderer + )) + )) + } } } contents.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(component.stickerContent))) contentTopPanels.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, - items: topStickertems + items: topStickerItems )))) contentIcons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputStickersIcon", @@ -125,6 +185,7 @@ public final class EntityKeyboardComponent: Component { maxSize: nil )), action: { + component.stickerContent.inputInteraction.openStickerSettings() } ).minSize(CGSize(width: 38.0, height: 38.0))))) @@ -143,7 +204,6 @@ public final class EntityKeyboardComponent: Component { )) } } - contentTopPanels.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, items: topEmojiItems diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift index 82a2ec6b70..16c2a40147 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift @@ -11,9 +11,14 @@ import BundleIconComponent private final class BottomPanelIconComponent: Component { let content: AnyComponent + let action: () -> Void - init(content: AnyComponent) { + init( + content: AnyComponent, + action: @escaping () -> Void + ) { self.content = content + self.action = action } static func ==(lhs: BottomPanelIconComponent, rhs: BottomPanelIconComponent) -> Bool { @@ -27,19 +32,31 @@ private final class BottomPanelIconComponent: Component { final class View: UIView { let contentView: ComponentHostView + var component: BottomPanelIconComponent? + override init(frame: CGRect) { self.contentView = ComponentHostView() + 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 { + self.component = component + let size = CGSize(width: 32.0, height: 32.0) let contentSize = self.contentView.update( @@ -169,12 +186,7 @@ final class EntityKeyboardBottomPanelComponent: Component { let rightAccessoryButtonSize = rightAccessoryButton.view.update( transition: rightAccessoryButtonTransition, - component: AnyComponent(Button( - content: rightAccessoryButtonComponent.component, - action: { [weak self] in - self?.component?.deleteBackwards() - } - ).minSize(CGSize(width: intrinsicHeight, height: intrinsicHeight))), + component: rightAccessoryButtonComponent.component, environment: {}, containerSize: CGSize(width: .greatestFiniteMagnitude, height: intrinsicHeight) ) @@ -208,6 +220,8 @@ final class EntityKeyboardBottomPanelComponent: Component { var iconTotalSize = CGSize() let iconSpacing: CGFloat = 22.0 + let navigateToContentId = panelEnvironment.navigateToContentId + for icon in panelEnvironment.contentIcons { validIconIds.append(icon.id) @@ -225,7 +239,10 @@ final class EntityKeyboardBottomPanelComponent: Component { let iconSize = iconView.update( transition: iconTransition, component: AnyComponent(BottomPanelIconComponent( - content: icon.component + content: icon.component, + action: { + navigateToContentId(icon.id) + } )), environment: {}, containerSize: CGSize(width: 32.0, height: 32.0) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 9e7732f6c4..1a3630a28c 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -252,14 +252,14 @@ final class EntityKeyboardTopPanelComponent: Component { self.itemViews[item.id] = itemView } - let itemFrame = itemLayout.contentFrame(at: index) - itemView.frame = itemFrame - let _ = itemView.update( + let itemOuterFrame = itemLayout.contentFrame(at: index) + let itemSize = itemView.update( transition: .immediate, component: item.content, environment: {}, - containerSize: itemFrame.size + containerSize: itemOuterFrame.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) } } var removedIds: [AnyHashable] = [] diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift new file mode 100644 index 0000000000..3b8a5c5c17 --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -0,0 +1,585 @@ +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 + +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() + self.playbackTimer = SwiftSignalKit.Timer(timeout: 1.0 / 30.0, repeat: true, completion: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.frameManager?.tick(timestamp: strongSelf.playbackTimestamp) + strongSelf.playbackTimestamp += 1.0 / 30.0 + }, 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 dimensions = file.dimensions { + self.thumbnailDisposable = (mediaGridMessageVideo(postbox: context.account.postbox, videoReference: .savedGif(media: self.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() { + let frameManager = SoftwareVideoLayerFrameManager(account: self.context.account, fileReference: .savedGif(media: self.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 final class InputInteraction { + public let performItemAction: (Item, UIView, CGRect) -> Void + + public init( + performItemAction: @escaping (Item, UIView, CGRect) -> Void + ) { + self.performItemAction = performItemAction + } + } + + public final class Item: Equatable { + public let file: TelegramMediaFile + + public init(file: TelegramMediaFile) { + self.file = file + } + + public static func ==(lhs: Item, rhs: Item) -> Bool { + if lhs === rhs { + return true + } + if lhs.file.fileId != rhs.file.fileId { + return false + } + + return true + } + } + + public let context: AccountContext + public let inputInteraction: InputInteraction + public let items: [Item] + + public init( + context: AccountContext, + inputInteraction: InputInteraction, + items: [Item] + ) { + self.context = context + self.inputInteraction = inputInteraction + self.items = items + } + + public static func ==(lhs: GifPagerContentComponent, rhs: GifPagerContentComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.inputInteraction !== rhs.inputInteraction { + return false + } + if lhs.items != rhs.items { + return false + } + + return true + } + + public final class View: UIView, 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 itemHorizontalSpace = width - self.containerInsets.left - self.containerInsets.right + self.itemSize = floor((width - self.horizontalSpacing * 2.0) / 3.0) + + self.itemsPerRow = Int((itemHorizontalSpace + self.horizontalSpacing) / (self.itemSize + self.horizontalSpacing)) + 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 { + 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 = min(self.itemCount - 1, (maxVisibleRow + 1) * self.itemsPerRow - 1) + + if maxVisibleIndex >= minVisibleIndex { + return minVisibleIndex ..< (maxVisibleIndex + 1) + } else { + return nil + } + } + } + + fileprivate final class ItemLayer: GifVideoLayer { + let item: Item + + private let file: TelegramMediaFile + private let placeholderColor: UIColor + 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 var displayPlaceholder: Bool = false + + init( + item: Item, + context: AccountContext, + groupId: String, + attemptSynchronousLoad: Bool, + file: TelegramMediaFile, + placeholderColor: UIColor + ) { + self.item = item + self.file = file + self.placeholderColor = placeholderColor + + super.init(context: context, file: file, synchronousLoad: attemptSynchronousLoad) + + self.updateDisplayPlaceholder(displayPlaceholder: true) + + self.started = { [weak self] in + self?.updateDisplayPlaceholder(displayPlaceholder: false) + } + + /*if attemptSynchronousLoad { + if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { + self.displayPlaceholder = true + + if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: self.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, 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 + } + + 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 = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() + } + })*/ + } + + 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) { + if self.displayPlaceholder == displayPlaceholder { + return + } + + self.displayPlaceholder = displayPlaceholder + + if displayPlaceholder { + let placeholderColor = self.placeholderColor + self.backgroundColor = placeholderColor.cgColor + } else { + self.backgroundColor = nil + } + } + } + + private let scrollView: UIScrollView + + private var visibleItemLayers: [MediaId: ItemLayer] = [:] + private var ignoreScrolling: Bool = false + + private var component: GifPagerContentComponent? + private var pagerEnvironment: PagerComponentChildEnvironment? + private var theme: PresentationTheme? + private var itemLayout: ItemLayout? + + override init(frame: CGRect) { + self.scrollView = UIScrollView() + + super.init(frame: frame) + + 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.addSubview(self.scrollView) + + 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 let component = self.component, let item = self.item(atPoint: recognizer.location(in: self)), let itemView = self.visibleItemLayers[item.file.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 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) + } + + 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) { + 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 offsetToClosestEdge = min(offsetToTopEdge, offsetToBottomEdge) + + let relativeOffset = scrollView.contentOffset.y - previousScrollingOffsetValue + self.pagerEnvironment?.onChildScrollingUpdate(PagerComponentChildEnvironment.ContentScrollingUpdate( + relativeOffset: relativeOffset, + absoluteOffsetToClosestEdge: offsetToClosestEdge, + 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 theme = self.theme, 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 { + let item = component.items[index] + let itemId = item.file.fileId + validIds.insert(itemId) + + let itemLayer: ItemLayer + if let current = self.visibleItemLayers[itemId] { + itemLayer = current + } else { + itemLayer = ItemLayer( + item: item, + context: component.context, + groupId: "savedGif", + attemptSynchronousLoad: attemptSynchronousLoads, + file: item.file, + placeholderColor: theme.chat.inputMediaPanel.stickersBackgroundColor + ) + self.scrollView.layer.addSublayer(itemLayer) + self.visibleItemLayers[itemId] = itemLayer + } + + itemLayer.frame = itemLayout.frame(at: index) + itemLayer.isVisibleForAnimations = true + } + } + + var removedIds: [MediaId] = [] + 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(component: GifPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.component = component + self.theme = environment[EntityKeyboardChildEnvironment.self].value.theme + + let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value + self.pagerEnvironment = pagerEnvironment + + 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 + } + 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/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/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..c052c0b77b --- /dev/null +++ b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift @@ -0,0 +1,35 @@ +import Foundation +import UIKit +import AnimationCache +import Display +import AnimatedStickerNode +import SwiftSignalKit + +public func cacheVideoAnimation(path: String, width: Int, height: Int, writer: AnimationCacheItemWriter) { + let queue = Queue() + queue.async { + guard let frameSource = makeVideoStickerDirectFrameSource(queue: queue, path: path, width: width, height: height, cachePathPrefix: nil) else { + return + } + let frameDuration = 1.0 / Double(frameSource.frameRate) + while true { + if let frame = frameSource.takeFrame(draw: true) { + //AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount, multiplyAlpha: true) + if case .argb = frame.type { + let frameWidth = frame.width + let frameHeight = frame.height + let bytesPerRow = frame.bytesPerRow + frame.data.withUnsafeBytes { bytes -> Void in + writer.add(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), length: bytes.count, width: Int(frameWidth), height: Int(frameHeight), bytesPerRow: Int(bytesPerRow), duration: frameDuration) + } + } else { + break + } + } else { + break + } + } + + writer.finish() + } +} diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 9ff570f2e4..e891ae810d 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -816,7 +816,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 @@ -1494,7 +1494,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G 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, sourceView, sourceRect in + }, sendSticker: { [weak self] fileReference, silentPosting, schedule, query, clearInput, sourceView, sourceRect, sourceLayer in guard let strongSelf = self else { return false } @@ -1568,8 +1568,23 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.messageTransitionNode.add(correlationId: correlationId, source: .stickerMediaInput(input: .inputPanelSearch(itemNode: sourceNode), replyPanel: replyPanel), initiated: {}) } 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 { - + } 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 + }) + }) } } @@ -1589,10 +1604,10 @@ 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.view, sourceRect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceView, sourceRect) return false } @@ -7583,9 +7598,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } } - }, sendSticker: { [weak self] file, clearInput, sourceView, 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, sourceView, sourceRect) ?? false + return strongSelf.controllerInteraction?.sendSticker(file, false, false, nil, clearInput, sourceView, sourceRect, sourceLayer) ?? false } else { return false } @@ -14846,7 +14861,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G break } }, sendFile: nil, sendSticker: { [weak self] f, sourceView, sourceRect in - return self?.interfaceInteraction?.sendSticker(f, true, sourceView, sourceRect) ?? false + 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) diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index 1fac0dc958..6beeb74fd9 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -73,8 +73,8 @@ public final class ChatControllerInteraction { let toggleMessagesSelection: ([MessageId], Bool) -> Void let sendCurrentMessage: (Bool) -> Void let sendMessage: (String) -> Void - let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect) -> Bool - let sendGif: (FileMediaReference, ASDisplayNode, CGRect, Bool, 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, ASDisplayNode, CGRect, Bool) -> Bool let requestMessageActionCallback: (MessageId, MemoryBuffer?, Bool, Bool) -> Void let requestMessageActionUrlAuth: (String, MessageActionUrlSubject) -> Void @@ -176,8 +176,8 @@ public final class ChatControllerInteraction { toggleMessagesSelection: @escaping ([MessageId], Bool) -> Void, sendCurrentMessage: @escaping (Bool) -> Void, sendMessage: @escaping (String) -> Void, - sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect) -> Bool, - sendGif: @escaping (FileMediaReference, ASDisplayNode, CGRect, Bool, 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, ASDisplayNode, CGRect, Bool) -> Bool, requestMessageActionCallback: @escaping (MessageId, MemoryBuffer?, Bool, Bool) -> Void, requestMessageActionUrlAuth: @escaping (String, MessageActionUrlSubject) -> Void, diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 81c407e371..873088a728 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2095,7 +2095,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if !self.didInitializeInputMediaNodeDataPromise, let interfaceInteraction = self.interfaceInteraction { self.didInitializeInputMediaNodeDataPromise = true - self.inputMediaNodeDataPromise.set(ChatEntityKeyboardInputNode.inputData(context: self.context, interfaceInteraction: interfaceInteraction)) + self.inputMediaNodeDataPromise.set(ChatEntityKeyboardInputNode.inputData(context: self.context, interfaceInteraction: interfaceInteraction, controllerInteraction: self.controllerInteraction)) } if self.inputMediaNode == nil && !"".isEmpty { diff --git a/submodules/TelegramUI/Sources/ChatEmptyNode.swift b/submodules/TelegramUI/Sources/ChatEmptyNode.swift index d14c8a99a1..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.view, 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.view, 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 index 3832a6764c..8c9f9cd9fc 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -12,24 +12,31 @@ import MultiAnimationRenderer import Postbox import TelegramCore import ComponentDisplayAdapters +import SettingsUI final class ChatEntityKeyboardInputNode: ChatInputNode { struct InputData: Equatable { let emoji: EmojiPagerContentComponent let stickers: EmojiPagerContentComponent + let gifs: GifPagerContentComponent init( emoji: EmojiPagerContentComponent, - stickers: EmojiPagerContentComponent + stickers: EmojiPagerContentComponent, + gifs: GifPagerContentComponent ) { self.emoji = emoji self.stickers = stickers + self.gifs = gifs } } - static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction) -> Signal { + static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction, controllerInteraction: ChatControllerInteraction) -> Signal { + let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) + let isPremiumDisabled = premiumConfiguration.isPremiumDisabled + let emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak interfaceInteraction] item, _, _ in + performItemAction: { [weak interfaceInteraction] item, _, _, _ in guard let interfaceInteraction = interfaceInteraction else { return } @@ -40,20 +47,38 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return } interfaceInteraction.backwardsDeleteText() + }, + openStickerSettings: { } ) let stickerInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak interfaceInteraction] item, view, rect in + performItemAction: { [weak interfaceInteraction] item, view, rect, layer in guard let interfaceInteraction = interfaceInteraction else { return } - let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, view, rect) + let _ = interfaceInteraction.sendSticker(.standalone(media: item.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) + } + ) + let gifInputInteraction = GifPagerContentComponent.InputInteraction( + performItemAction: { [weak controllerInteraction] item, view, rect in + guard let controllerInteraction = controllerInteraction else { + return + } + let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) } ) @@ -62,10 +87,24 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }) let animationRenderer = MultiAnimationRendererImpl() - let emojiItems: Signal = context.engine.stickers.loadedStickerPack(reference: .animatedEmoji, forceActualized: false) - |> map { animatedEmoji -> EmojiPagerContentComponent in + let emojiItems: Signal = combineLatest( + context.engine.stickers.loadedStickerPack(reference: .animatedEmoji, forceActualized: false), + context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudSavedStickers)) + ) + |> map { animatedEmoji, savedStickers -> EmojiPagerContentComponent in var emojiItems: [EmojiPagerContentComponent.Item] = [] + for item in savedStickers { + if let item = item.contents.get(SavedStickerItem.self) { + if item.file.isVideoSticker { + emojiItems.append(EmojiPagerContentComponent.Item( + emoji: "", + file: item.file + )) + } + } + } + switch animatedEmoji { case let .result(_, items, _): for item in items { @@ -97,24 +136,146 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { ) } - let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers] + 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 orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] - let stickerItems: Signal = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000) - |> map { view -> EmojiPagerContentComponent in + let stickerItems: Signal = combineLatest( + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000), + hasPremium + ) + |> map { view, hasPremium -> EmojiPagerContentComponent in struct ItemGroup { - var id: ItemCollectionId + var id: AnyHashable 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 + } + } + + 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( + emoji: "", + file: item.file + ) + + let groupId = "saved" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + } + } + } + + if let recentStickers = recentStickers { + var count = 0 + 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( + emoji: "", + file: item.media + ) + + let groupId = "recent" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + } + + count += 1 + if count >= 5 { + break + } + } + } + + 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( + emoji: "", + file: item.media + ) + + let groupId = "premium" + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + } + } + } + for entry in view.entries { guard let item = entry.item as? StickerPackItem else { continue } - if !item.file.isAnimatedSticker { - continue - } let resultItem = EmojiPagerContentComponent.Item( emoji: "", file: item.file @@ -135,10 +296,20 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { inputInteraction: stickerInputInteraction, itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in var title: String? - for (id, info, _) in view.collectionInfos { - if id == group.id, let info = info as? StickerPackCollectionInfo { - title = info.title.uppercased() - break + if group.id == AnyHashable("saved") { + title = nil + } else if group.id == AnyHashable("recent") { + //TODO:localize + title = "Recently Used".uppercased() + } else if group.id == AnyHashable("premium") { + //TODO:localize + title = "Premium".uppercased() + } else { + for (id, info, _) in view.collectionInfos { + if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { + title = info.title.uppercased() + break + } } } @@ -148,14 +319,31 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { ) } + let gifItems: Signal = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + |> map { savedGifs -> GifPagerContentComponent in + var items: [GifPagerContentComponent.Item] = [] + for gifItem in savedGifs { + items.append(GifPagerContentComponent.Item( + file: gifItem.contents.get(RecentMediaItem.self)!.media + )) + } + return GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + items: items + ) + } + return combineLatest(queue: .mainQueue(), emojiItems, - stickerItems + stickerItems, + gifItems ) - |> map { emoji, stickers -> InputData in + |> map { emoji, stickers, gifs -> InputData in return InputData( emoji: emoji, - stickers: stickers + stickers: stickers, + gifs: gifs ) } } @@ -196,6 +384,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { bottomInset: bottomInset, emojiContent: self.currentInputData.emoji, stickerContent: self.currentInputData.stickers, + gifContent: self.currentInputData.gifs, externalTopPanelContainer: self.externalTopPanelContainer, topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in guard let strongSelf = self else { diff --git a/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift b/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift index 3468153e01..288c9d53ba 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift @@ -238,7 +238,7 @@ final class ChatMediaInputGifPane: ChatMediaInputPane, UIScrollViewDelegate { if let (collection, result) = file.contextResult { let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, 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 76c63da189..80af486b9a 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -796,7 +796,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 +864,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 } @@ -1096,7 +1096,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 } @@ -1467,7 +1467,7 @@ 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) } @@ -1486,7 +1486,7 @@ 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) } @@ -1499,7 +1499,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) }))) } } @@ -1608,9 +1608,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.view, 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.view, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1622,9 +1622,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.view, 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.view, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1678,7 +1678,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 } @@ -1760,9 +1760,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.view, 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.view, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1774,9 +1774,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.view, 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.view, imageNode.bounds) + let _ = strongSelf.controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -1832,7 +1832,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 } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift index b18d419cf6..8c9fb1451f 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift @@ -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.view, 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) } } 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/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index f519798185..b2cc062ad2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -2311,18 +2311,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 { @@ -2342,7 +2337,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, @@ -2385,8 +2380,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/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index d7657cb0fd..2f57d3b0a4 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -1487,17 +1487,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 +1518,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 +1554,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/ChatMessageTransitionNode.swift b/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift index dfa894b6d0..bf079a44e7 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift @@ -111,17 +111,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 +176,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 +423,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 = sourceContainerView.convert(sourceRect, to: 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 +480,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/ChatRecentActionsController.swift b/submodules/TelegramUI/Sources/ChatRecentActionsController.swift index ba675ff969..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 diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index fa72a7a018..936cb29704 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() { diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 155e383412..13daf942a7 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -112,7 +112,7 @@ private final class DrawingStickersScreenNode: ViewControllerTracingNode { 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: { @@ -236,7 +236,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 +349,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 } diff --git a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift index dc2993be47..6e55f0cbb4 100644 --- a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift @@ -333,7 +333,7 @@ final class GifPaneSearchContentNode: ASDisplayNode & PaneSearchContentNode { if let (collection, result) = file.contextResult { let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode, 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/HorizontalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift index ce97e1b83e..a705670b73 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -164,7 +164,7 @@ final class HorizontalListContextResultsChatInputContextPanelNode: ChatInputCont if let strongSelf = self { 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, sourceView, sourceRect) ?? false + return strongSelf.interfaceInteraction?.sendSticker(file, false, sourceView, sourceRect, nil) ?? false } else { return false } diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index 1d99c75e84..930cdacc64 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -72,7 +72,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) }) } } @@ -180,7 +180,7 @@ final class HorizontalStickersChatContextPanelNode: ChatInputContextPanelNode { .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.view, 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) @@ -224,7 +224,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 } diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index ef2e3bd426..9a0280d1eb 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -111,9 +111,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.view, 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.view, imageNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), true, false, nil, true, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -125,9 +125,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.view, 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.view, imageNode.bounds) + let _ = controllerInteraction.sendSticker(.standalone(media: item.file), false, true, nil, true, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -179,7 +179,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 } @@ -576,7 +576,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/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 2029e31d4c..5c6dd1e3b0 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 diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 20756b514b..a89a74796a 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 @@ -2210,7 +2210,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 diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index b88389adb5..6d71ab7ba3 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 diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 0771a98da8..aa47eec6c7 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1280,7 +1280,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 diff --git a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift index 581ac2be30..92ea1c0b39 100644 --- a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift @@ -226,7 +226,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 } @@ -321,7 +321,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { } }, sendSticker: { [weak self] file, sourceView, sourceRect in if let strongSelf = self { - let _ = strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceView, sourceRect) + let _ = strongSelf.controllerInteraction.sendSticker(file, false, false, nil, false, sourceView, sourceRect, nil) } }, getItemIsPreviewed: { item in return inputNodeInteraction.previewedStickerPackItem == .pack(item) diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift index e474a5c6ee..d313b5cb28 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].view, self.nodes[i].bounds) + let _ = item.interfaceInteraction.sendSticker(.standalone(media: file), true, self.nodes[i].view, self.nodes[i].bounds, nil) break } } diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index 8f23e7f235..f72a055c94 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -136,7 +136,7 @@ final class StickersChatInputContextPanelNode: ChatInputContextPanelNode { .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.view, 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) @@ -180,7 +180,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 } From f2efd60154dcba1d9da230e3b6aa6a9ca132f6e8 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 22 Jun 2022 18:59:00 +0500 Subject: [PATCH 003/113] Various fixes --- submodules/TelegramUI/Sources/ChatMediaInputNode.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index 3eda31a7fb..e50820d4b6 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -295,7 +295,7 @@ func chatMediaInputGridEntries(view: ItemCollectionsView, savedStickers: Ordered let filteredTrending = trendingPacks.filter { !installedPacks.contains($0.info.id) } if !trendingIsDismissed && !filteredTrending.isEmpty { - entries.append(.trendingList(theme: theme, strings: strings, packs: filteredTrending, isPremium: false)) + entries.append(.trendingList(theme: theme, strings: strings, packs: filteredTrending, isPremium: trendingIsPremium)) } if let recentStickers = recentStickers, !recentStickers.items.isEmpty { From a573daa9494c0c4e83b7e3e03119678d1e69edf7 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 23 Jun 2022 18:41:21 +0500 Subject: [PATCH 004/113] Various fixes --- submodules/Display/Source/ListView.swift | 3 ++ .../ChatMessageAnimatedStickerItemNode.swift | 46 +++++++++---------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/submodules/Display/Source/ListView.swift b/submodules/Display/Source/ListView.swift index 25a669b16c..b482bc67ad 100644 --- a/submodules/Display/Source/ListView.swift +++ b/submodules/Display/Source/ListView.swift @@ -3347,6 +3347,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture if progress == 1.0 { for itemNode in temporaryPreviousNodes { + itemNode.visibility = .none itemNode.removeFromSupernode() itemNode.extractedBackgroundNode?.removeFromSupernode() } @@ -3360,6 +3361,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture } else { animation.completion = { _ in for itemNode in temporaryPreviousNodes { + itemNode.visibility = .none itemNode.removeFromSupernode() itemNode.extractedBackgroundNode?.removeFromSupernode() } @@ -3442,6 +3444,7 @@ open class ListView: ASDisplayNode, UIScrollViewAccessibilityDelegate, UIGesture private func removeItemNodeAtIndex(_ index: Int) { let node = self.itemNodes[index] self.itemNodes.remove(at: index) + node.visibility = .none node.removeFromSupernode() node.extractedBackgroundNode?.removeFromSupernode() node.accessoryItemNode?.removeFromSupernode() diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 8df35f3722..f6fbf62026 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -402,11 +402,11 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } } - private var visibilityStatus: Bool = false { + private var visibilityStatus: Bool? { didSet { if self.visibilityStatus != oldValue { self.updateVisibility() - self.haptic?.enabled = self.visibilityStatus + self.haptic?.enabled = self.visibilityStatus == true } } } @@ -593,28 +593,18 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { } } - let isPlaying = self.visibilityStatus && !self.forceStopAnimations - if let animationNode = self.animationNode as? AnimatedStickerNode { - if !isPlaying { - for decorationNode in self.additionalAnimationNodes { - if let transitionNode = item.controllerInteraction.getMessageTransitionNode() { - decorationNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak decorationNode] _ in - if let decorationNode = decorationNode { - transitionNode.remove(decorationNode: decorationNode) - } - }) - } - } - self.additionalAnimationNodes.removeAll() - - if let overlayMeshAnimationNode = self.overlayMeshAnimationNode { - self.overlayMeshAnimationNode = nil - if let transitionNode = item.controllerInteraction.getMessageTransitionNode() { - transitionNode.remove(decorationNode: overlayMeshAnimationNode) - } + let isPlaying = self.visibilityStatus == true && !self.forceStopAnimations + if !isPlaying { + self.removeAdditionalAnimations() + + if let overlayMeshAnimationNode = self.overlayMeshAnimationNode { + self.overlayMeshAnimationNode = nil + if let transitionNode = item.controllerInteraction.getMessageTransitionNode() { + transitionNode.remove(decorationNode: overlayMeshAnimationNode) } } - + } + if let animationNode = self.animationNode as? AnimatedStickerNode { if self.isPlaying != isPlaying { self.isPlaying = isPlaying @@ -1721,10 +1711,20 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { self.additionalAnimationNodes.append(decorationNode) - additionalAnimationNode.play() + additionalAnimationNode.visibility = true } } + private func removeAdditionalAnimations() { + for decorationNode in self.additionalAnimationNodes { + if let additionalAnimationNode = decorationNode.contentView.asyncdisplaykit_node as? AnimatedStickerNode { + additionalAnimationNode.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak additionalAnimationNode] _ in + additionalAnimationNode?.visibility = false + }) + } + } + } + private func gestureRecognized(gesture: TapLongTapOrDoubleTapGesture, location: CGPoint, recognizer: TapLongTapOrDoubleTapGestureRecognizer?) -> InternalBubbleTapAction? { switch gesture { case .tap: From c112bc5146a48d9861fd09205cd33bb2de208cf6 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jun 2022 02:06:02 +0100 Subject: [PATCH 005/113] Entity input: improved animation cache and rendering --- .../Sources/ChatController.swift | 13 + .../Source/ASTextKitComponents.mm | 19 +- .../AttachmentTextInputPanelNode.swift | 2 +- .../ChatPanelInterfaceInteraction.swift | 4 +- .../ManagedFile/Sources/ManagedFile.swift | 19 + submodules/Postbox/Sources/MediaBox.swift | 21 + submodules/Postbox/Sources/MediaBoxFile.swift | 2 +- submodules/TelegramApi/Sources/Api0.swift | 1 + submodules/TelegramApi/Sources/Api11.swift | 34 + .../ApiUtils/StoreMessage_Telegram.swift | 6 +- .../TextEntitiesMessageAttribute.swift | 5 +- .../ManagedSecretChatOutgoingOperations.swift | 4 +- .../Sources/State/Serialization.swift | 2 +- .../SyncCore/SyncCore_TelegramMediaFile.swift | 44 +- ...yncCore_TextEntitiesMessageAttribute.swift | 26 +- submodules/TelegramUI/BUILD | 1 + .../Components/AnimationCache/BUILD | 1 + .../Components/AnimationCache/DCT/BUILD | 23 + .../DCT/PublicHeaders/DCT/DCT.h | 14 + .../DCT/PublicHeaders/DCT/YuvConversion.h | 9 + .../AnimationCache/DCT/Sources/DCT.m | 991 ++++++++++++++++++ .../DCT/Sources/YuvConversion.m | 99 ++ .../Sources/AnimationCache.swift | 578 ++++++++-- .../AnimationCache/Sources/ImageData.swift | 231 ++++ .../Components/EmojiTextAttachmentView/BUILD | 1 + .../Sources/EmojiTextAttachmentView.swift | 142 ++- .../Sources/EmojiPagerContentComponent.swift | 66 +- .../Sources/LottieAnimationCache.swift | 29 +- .../Sources/MultiAnimationRenderer.swift | 180 ++-- .../Sources/VideoAnimationCache.swift | 41 +- .../TelegramUI/Sources/ChatController.swift | 15 +- .../Sources/ChatEntityKeyboardInputNode.swift | 66 +- .../ChatMessageTextBubbleContentNode.swift | 50 +- .../Sources/ChatTextInputPanelNode.swift | 108 +- .../Sources/ChatTextInputAttributes.swift | 69 +- .../Sources/GenerateTextEntities.swift | 22 +- .../Sources/StringWithAppliedEntities.swift | 2 + 37 files changed, 2557 insertions(+), 383 deletions(-) create mode 100644 submodules/TelegramUI/Components/AnimationCache/DCT/BUILD create mode 100644 submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h create mode 100644 submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/YuvConversion.h create mode 100644 submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m create mode 100644 submodules/TelegramUI/Components/AnimationCache/DCT/Sources/YuvConversion.m create mode 100644 submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 63a69e990c..87464bb853 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -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.decode(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.encode(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), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) } } return result diff --git a/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm index 7bf26bcf8b..7bfee153fa 100644 --- a/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm +++ b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm @@ -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]; } diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index 43a96c5d10..c0afa5705a 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -242,7 +242,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS private var spoilersRevealed = false - private var emojiViewProvider: ((String) -> UIView)? + private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? private var maxCaptionLength: Int32? diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift index cae532aea0..89803b3707 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatPanelInterfaceInteraction.swift @@ -144,7 +144,7 @@ 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: (String) -> Void + public let insertText: (NSAttributedString) -> Void public let backwardsDeleteText: () -> Void public let chatController: () -> ViewController? public let statuses: ChatPanelInterfaceInteractionStatuses? @@ -240,7 +240,7 @@ public final class ChatPanelInterfaceInteraction { displayCopyProtectionTip: @escaping (ASDisplayNode, Bool) -> Void, openWebView: @escaping (String, String, Bool, Bool) -> Void, updateShowWebView: @escaping ((Bool) -> Bool) -> Void, - insertText: @escaping (String) -> Void, + insertText: @escaping (NSAttributedString) -> Void, backwardsDeleteText: @escaping () -> Void, chatController: @escaping () -> ViewController?, statuses: ChatPanelInterfaceInteractionStatuses? diff --git a/submodules/ManagedFile/Sources/ManagedFile.swift b/submodules/ManagedFile/Sources/ManagedFile.swift index d43ab46369..ba5c4a5cbf 100644 --- a/submodules/ManagedFile/Sources/ManagedFile.swift +++ b/submodules/ManagedFile/Sources/ManagedFile.swift @@ -19,6 +19,7 @@ public final class ManagedFile { private let queue: Queue? private let fd: Int32 private let mode: Mode + private var isClosed: Bool = false public init?(queue: Queue?, path: String, mode: Mode) { if let queue = queue { @@ -48,16 +49,27 @@ public final class ManagedFile { } deinit { + if let queue = self.queue { + assert(queue.isCurrent()) + } + if !self.isClosed { + close(self.fd) + } + } + + public func _unsafeClose() { if let queue = self.queue { assert(queue.isCurrent()) } close(self.fd) + self.isClosed = true } public func write(_ data: UnsafeRawPointer, count: Int) -> 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/Postbox/Sources/MediaBox.swift b/submodules/Postbox/Sources/MediaBox.swift index 5a6a01015f..f1cbdb1419 100644 --- a/submodules/Postbox/Sources/MediaBox.swift +++ b/submodules/Postbox/Sources/MediaBox.swift @@ -1239,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/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 4f77dde770..560e7fde82 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -433,6 +433,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[-727707947] = { 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) } diff --git a/submodules/TelegramApi/Sources/Api11.swift b/submodules/TelegramApi/Sources/Api11.swift index 8172159a5c..184426636f 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -7,6 +7,7 @@ public extension Api { case messageEntityBotCommand(offset: Int32, length: Int32) case messageEntityCashtag(offset: Int32, length: Int32) case messageEntityCode(offset: Int32, length: Int32) + case messageEntityCustomEmoji(offset: Int32, length: Int32, stickerset: Api.InputStickerSet, documentId: Int64) case messageEntityEmail(offset: Int32, length: Int32) case messageEntityHashtag(offset: Int32, length: Int32) case messageEntityItalic(offset: Int32, length: Int32) @@ -73,6 +74,15 @@ public extension Api { serializeInt32(offset, buffer: buffer, boxed: false) serializeInt32(length, buffer: buffer, boxed: false) break + case .messageEntityCustomEmoji(let offset, let length, let stickerset, let documentId): + if boxed { + buffer.appendInt32(-727707947) + } + serializeInt32(offset, buffer: buffer, boxed: false) + serializeInt32(length, buffer: buffer, boxed: false) + stickerset.serialize(buffer, true) + serializeInt64(documentId, buffer: buffer, boxed: false) + break case .messageEntityEmail(let offset, let length): if boxed { buffer.appendInt32(1692693954) @@ -186,6 +196,8 @@ public extension Api { 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 stickerset, let documentId): + return ("messageEntityCustomEmoji", [("offset", String(describing: offset)), ("length", String(describing: length)), ("stickerset", String(describing: stickerset)), ("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): @@ -318,6 +330,28 @@ public extension Api { return nil } } + public static func parse_messageEntityCustomEmoji(_ reader: BufferReader) -> MessageEntity? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int32? + _2 = reader.readInt32() + var _3: Api.InputStickerSet? + if let signature = reader.readInt32() { + _3 = Api.parse(reader, signature: signature) as? Api.InputStickerSet + } + var _4: Int64? + _4 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + if _c1 && _c2 && _c3 && _c4 { + return Api.MessageEntity.messageEntityCustomEmoji(offset: _1!, length: _2!, stickerset: _3!, documentId: _4!) + } + else { + return nil + } + } public static func parse_messageEntityEmail(_ reader: BufferReader) -> MessageEntity? { var _1: Int32? _1 = reader.readInt32() diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index a9726d26a4..d18917198a 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -374,8 +374,10 @@ 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, stickerset, documentId): + if let stickerPack = StickerPackReference(apiInputSet: stickerset) { + result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .CustomEmoji(stickerPack: stickerPack, fileId: documentId))) + } } } return result diff --git a/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift b/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift index 25da7187cb..6c3e4b7dcb 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(stickerPack, fileId): + apiEntities.append(.messageEntityCustomEmoji(offset: offset, length: length, stickerset: stickerPack.apiInputStickerSet, documentId: fileId)) case .Custom: break } diff --git a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift index 8cd7216db5..50b56a3a48 100644 --- a/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift @@ -715,7 +715,7 @@ private func decryptedEntities73(_ entities: [MessageTextEntity]?) -> [SecretApi break case .Spoiler: break - case .AnimatedEmoji: + case .CustomEmoji: break case .Custom: break @@ -768,7 +768,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/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/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index c01106354f..64a55fe83e 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -12,7 +12,7 @@ private let typeHintFileIsLarge: Int32 = 7 private let typeHintIsValidated: Int32 = 8 private let typeNoPremium: Int32 = 9 -public enum StickerPackReference: PostboxCoding, Hashable, Equatable { +public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { case id(id: Int64, accessHash: Int64) case name(String) case animatedEmoji @@ -37,6 +37,27 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable { } } + public init(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 + default: + self = .name("") + assertionFailure() + } + } + public func encode(_ encoder: PostboxEncoder) { switch self { case let .id(id, accessHash): @@ -56,6 +77,27 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable { } } + 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") + } + } + public static func ==(lhs: StickerPackReference, rhs: StickerPackReference) -> Bool { switch lhs { case let .id(id, accessHash): diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift index 6906d5ba9f..7c6bbe7d3d 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,11 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { case 17: self.type = .Spoiler case 18: - self.type = .AnimatedEmoji(decoder.decodeObjectForKey("mediaId") as? MediaId) + if let stickerPack = decoder.decodeObjectForKey("s", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference { + self.type = .CustomEmoji(stickerPack: stickerPack, fileId: decoder.decodeInt64ForKey("f", orElse: 0)) + } else { + self.type = .Unknown + } case Int32.max: self.type = .Custom(type: decoder.decodeInt32ForKey("type", orElse: 0)) default: @@ -130,7 +134,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.decode(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 +185,10 @@ 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") - } + encoder.encodeObject(stickerPack, forKey: "s") + encoder.encodeInt64(fileId, forKey: "f") case let .Custom(type): encoder.encodeInt32(Int32.max, forKey: "_rawValue") encoder.encodeInt32(type, forKey: "type") @@ -238,11 +239,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.encode(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") diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 371cc76040..ccf6ae5604 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -285,6 +285,7 @@ swift_library( "//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/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", "//submodules/Media/ConvertOpusToAAC:ConvertOpusToAAC", diff --git a/submodules/TelegramUI/Components/AnimationCache/BUILD b/submodules/TelegramUI/Components/AnimationCache/BUILD index c5773d4849..3e79cc1f13 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/DCT:DCT", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/BUILD b/submodules/TelegramUI/Components/AnimationCache/DCT/BUILD new file mode 100644 index 0000000000..f98db65bc2 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/DCT/BUILD @@ -0,0 +1,23 @@ + +objc_library( + name = "DCT", + enable_modules = True, + module_name = "DCT", + srcs = glob([ + "Sources/**/*.m", + "Sources/**/*.h", + ]), + hdrs = glob([ + "PublicHeaders/**/*.h", + ]), + includes = [ + "PublicHeaders", + ], + sdk_frameworks = [ + "Foundation", + "Accelerate", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h b/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h new file mode 100644 index 0000000000..01fa6dc26c --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h @@ -0,0 +1,14 @@ +#ifndef DctImageTransform_h +#define DctImageTransform_h + +#import + +#import + +NSData *generateForwardDctData(int quality); +void performForwardDct(uint8_t const *pixels, int16_t *coefficients, int width, int height, int bytesPerRow, NSData *dctData); + +NSData *generateInverseDctData(int quality); +void performInverseDct(int16_t const *coefficients, uint8_t *pixels, int width, int height, int coefficientsPerRow, int bytesPerRow, NSData *idctData); + +#endif /* DctImageTransform_h */ diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/YuvConversion.h b/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/YuvConversion.h new file mode 100644 index 0000000000..a7ceddecb9 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/YuvConversion.h @@ -0,0 +1,9 @@ +#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); + +#endif /* YuvConversion_h */ diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m b/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m new file mode 100644 index 0000000000..b01c769007 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m @@ -0,0 +1,991 @@ +#import + +typedef long JLONG; + +typedef unsigned char JSAMPLE; +#define GETJSAMPLE(value) ((int)(value)) + +#define MAXJSAMPLE 255 +#define CENTERJSAMPLE 128 + +typedef short JCOEF; + +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 JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ +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 */ + +typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ + +#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 +}; + +typedef short DCTELEM; /* prefer 16 bit with SIMD for parellelism */ +typedef unsigned short UDCTELEM; +typedef unsigned int UDCTELEM2; + +static void jsimd_fdct_ifast_neon(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); +} + +static void jsimd_idct_ifast_neon(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); +} + +static 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; +} + +static 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 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; +} + +static void jpeg_add_quant_table(DCTELEM *qtable, DCTELEM *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; + } +} + +static void jpeg_set_quality(DCTELEM *qtable, 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, std_luminance_quant_tbl, quality, false); +} + +static void getDivisors(DCTELEM *dtbl, DCTELEM *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])) { + //fdct->quantize = quantize; + printf("here\n"); + } + } +} + +static 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; + } +} + +NSData *generateForwardDctData(int quality) { + NSMutableData *divisors = [[NSMutableData alloc] initWithLength:DCTSIZE2 * 4 * sizeof(DCTELEM)]; + + DCTELEM qtable[DCTSIZE2]; + jpeg_set_quality(qtable, quality); + + getDivisors((DCTELEM *)divisors.mutableBytes, qtable); + + return divisors; +} + +NSData *generateInverseDctData(int quality) { + NSMutableData *divisors = [[NSMutableData alloc] initWithLength:DCTSIZE2 * sizeof(IFAST_MULT_TYPE)]; + IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)divisors.mutableBytes; + + DCTELEM qtable[DCTSIZE2]; + jpeg_set_quality(qtable, quality); + +#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); + } + + return divisors; +} + +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, NSData *dctData) { + DCTELEM *divisors = (DCTELEM *)dctData.bytes; + + 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; + } + } + + jsimd_fdct_ifast_neon(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, NSData *idctData) { + IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)idctData.bytes; + + 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)]; + } + } + + jsimd_idct_ifast_neon(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]; + } + } + } + } +} diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/YuvConversion.m b/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/YuvConversion.m new file mode 100644 index 0000000000..25b244d5e1 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/YuvConversion.m @@ -0,0 +1,99 @@ +#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); +} diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 3201000137..2f6e8197d6 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -3,6 +3,7 @@ import UIKit import SwiftSignalKit import CryptoUtils import ManagedFile +import Compression public final class AnimationCacheItemFrame { public enum Format { @@ -25,19 +26,51 @@ public final class AnimationCacheItemFrame { public final class AnimationCacheItem { public let numFrames: Int private let getFrameImpl: (Int) -> AnimationCacheItemFrame? + private let getFrameIndexImpl: (Double) -> Int - public init(numFrames: Int, getFrame: @escaping (Int) -> AnimationCacheItemFrame?) { + public init(numFrames: Int, getFrame: @escaping (Int) -> AnimationCacheItemFrame?, getFrameIndexImpl: @escaping (Double) -> Int) { self.numFrames = numFrames self.getFrameImpl = getFrame + self.getFrameIndexImpl = getFrameIndexImpl } public func getFrame(index: Int) -> AnimationCacheItemFrame? { return self.getFrameImpl(index) } + + public func getFrame(at duration: Double) -> AnimationCacheItemFrame? { + let index = self.getFrameIndexImpl(duration) + return self.getFrameImpl(index) + } +} + +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) -> Void, proposedWidth: Int, proposedHeight: Int, duration: Double) func finish() } @@ -53,7 +86,8 @@ public final class AnimationCacheItemResult { public protocol AnimationCache: AnyObject { func get(sourceId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Signal - func getSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? + 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 { @@ -80,11 +114,82 @@ private func itemSubpath(hashString: String) -> (directory: String, fileName: St return (directory, hashString) } +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 AnimationCacheItemWriterImpl: AnimationCacheItemWriter { - private struct ParameterSet: Equatable { - var width: Int - var height: Int - var bytesPerRow: Int + struct CompressedResult { + var animationPath: String + var firstFramePath: String } private struct FrameMetadata { @@ -93,10 +198,19 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { var duration: Double } - private let file: ManagedFile - private let completion: (Bool) -> Void + let queue: Queue + var isCancelled: Bool = false - private var currentParameterSet: ParameterSet? + private let decompressedPath: String + private let compressedPath: String + private let firstFramePath: String + private var file: ManagedFile? + 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 @@ -104,44 +218,141 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { private var frames: [FrameMetadata] = [] private var contentLength: Int = 0 + private let dctQuality: Int + private let lock = Lock() - init?(tempPath: String, completion: @escaping (Bool) -> Void) { - guard let file = ManagedFile(queue: nil, path: tempPath, mode: .readwrite) else { + init?(queue: Queue, allocateTempFile: @escaping () -> String, completion: @escaping (CompressedResult?) -> Void) { + self.dctQuality = 67 + + self.queue = queue + self.decompressedPath = allocateTempFile() + self.compressedPath = allocateTempFile() + self.firstFramePath = allocateTempFile() + + guard let file = ManagedFile(queue: nil, path: self.decompressedPath, mode: .readwrite) else { return nil } self.file = file self.completion = completion } - func add(bytes: UnsafeRawPointer, length: Int, width: Int, height: Int, bytesPerRow: Int, duration: Double) { + func add(with drawingBlock: (AnimationCacheItemDrawingSurface) -> Void, proposedWidth: Int, proposedHeight: Int, duration: Double) { + if self.isFailed || self.isFinished { + return + } + self.lock.locked { - if self.isFailed { + guard !self.isFailed, !self.isFinished, let file = self.file 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(proposedWidth, 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) + 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) + 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, current.quality == self.dctQuality { + dctData = current + } else { + dctData = DctData(quality: self.dctQuality) + self.currentDctData = dctData + } + + surface.argbPlane.data.withUnsafeMutableBytes { bytes -> Void in + drawingBlock(AnimationCacheItemDrawingSurface( + argb: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), + width: width, + height: height, + bytesPerRow: surface.argbPlane.bytesPerRow, + length: bytes.count + )) + } + + surface.toYUVA420(target: yuvaSurface) + yuvaSurface.dct(dctData: dctData, target: dctCoefficients) + + if isFirstFrame { + file.write(2 as UInt32) + + file.write(UInt32(dctCoefficients.yPlane.width)) + file.write(UInt32(dctCoefficients.yPlane.height)) + file.write(UInt32(dctData.quality)) + + self.contentLengthOffset = Int(file.position()) + file.write(0 as UInt32) + } + + let framePosition = Int(file.position()) + assert(framePosition >= 0) + var frameLength = 0 + + 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() + } + + dctPlane.data.withUnsafeBytes { bytes in + let _ = file.write(bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: bytes.count) + } + frameLength += dctPlane.data.count + } + + self.frames.append(FrameMetadata(offset: framePosition, length: frameLength, duration: duration)) + + self.contentLength += frameLength } } @@ -152,27 +363,96 @@ 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 else { + self.isFailed = true + return + } + assert(contentLengthOffset >= 0) + + let metadataPosition = file.position() + file.seek(position: Int64(contentLengthOffset)) + file.write(UInt32(self.contentLength)) + + file.seek(position: metadataPosition) + file.write(UInt32(self.frames.count)) + for frame in self.frames { + file.write(UInt32(frame.offset)) + file.write(UInt32(frame.length)) + file.write(Float32(frame.duration)) + } + + if !self.frames.isEmpty, let dctCoefficients = self.currentDctCoefficients, let dctData = self.currentDctData { + var firstFrameData = Data(capacity: 4 * 5 + self.frames[0].length) + + writeUInt32(data: &firstFrameData, value: 2 as UInt32) + writeUInt32(data: &firstFrameData, value: UInt32(dctCoefficients.yPlane.width)) + writeUInt32(data: &firstFrameData, value: UInt32(dctCoefficients.yPlane.height)) + writeUInt32(data: &firstFrameData, value: UInt32(dctData.quality)) + + writeUInt32(data: &firstFrameData, value: UInt32(self.frames[0].length)) + let firstFrameStart = 4 * 5 + + file.seek(position: Int64(self.frames[0].offset)) + firstFrameData.count += self.frames[0].length + firstFrameData.withUnsafeMutableBytes { bytes in + let _ = file.read(bytes.baseAddress!.advanced(by: 4 * 5), self.frames[0].length) + } + + writeUInt32(data: &firstFrameData, value: UInt32(1)) + writeUInt32(data: &firstFrameData, value: UInt32(firstFrameStart)) + writeUInt32(data: &firstFrameData, value: UInt32(self.frames[0].length)) + writeFloat32(data: &firstFrameData, value: Float32(1.0)) + + guard let compressedFirstFrameData = compressData(data: firstFrameData, addSizeHeader: true) else { + self.isFailed = true + return + } + guard let _ = try? compressedFirstFrameData.write(to: URL(fileURLWithPath: self.firstFramePath)) else { + self.isFailed = true + return + } + } else { self.isFailed = true return } - let metadataPosition = self.file.position() - self.file.seek(position: Int64(contentLengthOffset)) - self.file.write(UInt32(self.contentLength)) - - 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)) + if !self.isFailed { + self.file = nil + + file._unsafeClose() + + guard let uncompressedData = try? Data(contentsOf: URL(fileURLWithPath: self.decompressedPath), options: .alwaysMapped) else { + self.isFailed = true + return + } + guard let compressedData = compressData(data: uncompressedData) else { + self.isFailed = true + return + } + guard let compressedFile = ManagedFile(queue: nil, path: self.compressedPath, mode: .readwrite) else { + self.isFailed = true + return + } + compressedFile.write(Int32(uncompressedData.count)) + let _ = compressedFile.write(compressedData) + compressedFile._unsafeClose() } } } if shouldComplete { - self.completion(!self.isFailed) + let _ = try? FileManager.default.removeItem(atPath: self.decompressedPath) + + if !self.isFailed { + self.completion(CompressedResult( + animationPath: self.compressedPath, + firstFramePath: self.firstFramePath + )) + } else { + let _ = try? FileManager.default.removeItem(atPath: self.compressedPath) + let _ = try? FileManager.default.removeItem(atPath: self.firstFramePath) + self.completion(nil) + } } } } @@ -185,12 +465,34 @@ private final class AnimationCacheItemAccessor { private let data: Data private let frameMapping: [Int: FrameInfo] - private let format: AnimationCacheItemFrame.Format + private let durationMapping: [Double] + private let totalDuration: Double - init(data: Data, frameMapping: [Int: FrameInfo], format: AnimationCacheItemFrame.Format) { + private var currentYUVASurface: ImageYUVA420 + private var currentDctData: DctData + private var currentDctCoefficients: DctCoefficientsYUVA420 + + init(data: Data, frameMapping: [FrameInfo], width: Int, height: Int, dctQuality: Int) { self.data = data - self.frameMapping = frameMapping - self.format = format + + var resultFrameMapping: [Int: FrameInfo] = [:] + var durationMapping: [Double] = [] + var totalDuration: Double = 0.0 + + for i in 0 ..< frameMapping.count { + let frame = frameMapping[i] + resultFrameMapping[i] = frame + totalDuration += frame.duration + durationMapping.append(totalDuration) + } + + self.frameMapping = resultFrameMapping + self.durationMapping = durationMapping + self.totalDuration = totalDuration + + self.currentYUVASurface = ImageYUVA420(width: width, height: height) + self.currentDctData = DctData(quality: dctQuality) + self.currentDctCoefficients = DctCoefficientsYUVA420(width: width, height: height) } func getFrame(index: Int) -> AnimationCacheItemFrame? { @@ -198,7 +500,56 @@ private final class AnimationCacheItemAccessor { return nil } - return AnimationCacheItemFrame(data: data, range: frameInfo.range, format: self.format, duration: frameInfo.duration) + let currentSurface = ImageARGB(width: self.currentYUVASurface.yPlane.width, height: self.currentYUVASurface.yPlane.height) + + var frameDataOffset = 0 + let frameLength = frameInfo.range.upperBound - frameInfo.range.lowerBound + for i in 0 ..< 4 { + let dctPlane: DctCoefficientPlane + switch i { + case 0: + dctPlane = self.currentDctCoefficients.yPlane + case 1: + dctPlane = self.currentDctCoefficients.uPlane + case 2: + dctPlane = self.currentDctCoefficients.vPlane + case 3: + dctPlane = self.currentDctCoefficients.aPlane + default: + preconditionFailure() + } + + if frameDataOffset + dctPlane.data.count > frameLength { + break + } + + dctPlane.data.withUnsafeMutableBytes { targetBuffer -> Void in + self.data.copyBytes(to: targetBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), from: (frameInfo.range.lowerBound + frameDataOffset) ..< (frameInfo.range.lowerBound + frameDataOffset + targetBuffer.count)) + } + + frameDataOffset += dctPlane.data.count + } + + self.currentDctCoefficients.idct(dctData: self.currentDctData, target: self.currentYUVASurface) + self.currentYUVASurface.toARGB(target: currentSurface) + + return AnimationCacheItemFrame(data: currentSurface.argbPlane.data, range: 0 ..< currentSurface.argbPlane.data.count, format: .rgba(width: currentSurface.argbPlane.width, height: currentSurface.argbPlane.height, bytesPerRow: currentSurface.argbPlane.bytesPerRow), duration: frameInfo.duration) + } + + func getFrameIndex(duration: Double) -> Int { + if self.totalDuration == 0.0 { + return 0 + } + if self.durationMapping.count <= 1 { + return 0 + } + let normalizedDuration = duration.truncatingRemainder(dividingBy: self.totalDuration) + for i in 1 ..< self.durationMapping.count { + if normalizedDuration < self.durationMapping[i] { + return i - 1 + } + } + return self.durationMapping.count - 1 } } @@ -213,10 +564,54 @@ private func readUInt32(data: Data, offset: Int) -> UInt32 { return value } +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) + } + }) + + 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 func loadItem(path: String) -> AnimationCacheItem? { - guard let data = try? Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped) else { + guard let compressedData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped) else { return nil } + + if compressedData.count < 4 { + return nil + } + let decompressedSize = readUInt32(data: compressedData, offset: 0) + + if decompressedSize <= 0 || decompressedSize > 20 * 1024 * 1024 { + return nil + } + guard let data = decompressData(data: compressedData, range: 4 ..< compressedData.count, decompressedSize: Int(decompressedSize)) else { + return nil + } + let dataLength = data.count var offset = 0 @@ -226,7 +621,7 @@ private func loadItem(path: String) -> AnimationCacheItem? { } let formatVersion = readUInt32(data: data, offset: offset) offset += 4 - if formatVersion != 1 { + if formatVersion != 2 { return nil } @@ -245,7 +640,7 @@ private func loadItem(path: String) -> AnimationCacheItem? { guard dataLength >= offset + 4 else { return nil } - let bytesPerRow = readUInt32(data: data, offset: offset) + let dctQuality = readUInt32(data: data, offset: offset) offset += 4 guard dataLength >= offset + 4 else { @@ -262,8 +657,8 @@ private func loadItem(path: String) -> AnimationCacheItem? { let numFrames = readUInt32(data: data, offset: offset) offset += 4 - var frameMapping: [Int: AnimationCacheItemAccessor.FrameInfo] = [:] - for i in 0 ..< Int(numFrames) { + var frameMapping: [AnimationCacheItemAccessor.FrameInfo] = [] + for _ in 0 ..< Int(numFrames) { guard dataLength >= offset + 4 + 4 + 4 else { return nil } @@ -272,16 +667,18 @@ private func loadItem(path: String) -> AnimationCacheItem? { offset += 4 let frameLength = readUInt32(data: data, offset: offset) offset += 4 - let frameDuration = readUInt32(data: data, offset: offset) + let frameDuration = readFloat32(data: data, offset: offset) offset += 4 - frameMapping[i] = AnimationCacheItemAccessor.FrameInfo(range: Int(frameStart) ..< Int(frameStart + frameLength), duration: Double(frameDuration)) + frameMapping.append(AnimationCacheItemAccessor.FrameInfo(range: Int(frameStart) ..< Int(frameStart + frameLength), duration: Double(frameDuration))) } - let itemAccessor = AnimationCacheItemAccessor(data: data, frameMapping: frameMapping, format: .rgba(width: Int(width), height: Int(height), bytesPerRow: Int(bytesPerRow))) + let itemAccessor = AnimationCacheItemAccessor(data: data, frameMapping: frameMapping, width: Int(width), height: Int(height), dctQuality: Int(dctQuality)) return AnimationCacheItem(numFrames: Int(numFrames), getFrame: { index in return itemAccessor.getFrame(index: index) + }, getFrameIndexImpl: { duration in + return itemAccessor.getFrameIndex(duration: duration) }) } @@ -300,10 +697,14 @@ 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 + self.fetchQueues = (0 ..< 2).map { _ in Queue() } self.basePath = basePath self.allocateTempFile = allocateTempFile } @@ -315,9 +716,10 @@ public final class AnimationCacheImpl: AnimationCache { let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId + "-\(Int(size.width))x\(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) { - updateResult(AnimationCacheItemResult(item: loadItem(path: itemPath), isFinal: true)) + if FileManager.default.fileExists(atPath: itemPath), let item = loadItem(path: itemPath) { + updateResult(AnimationCacheItemResult(item: item, isFinal: true)) return EmptyDisposable } @@ -338,8 +740,7 @@ public final class AnimationCacheImpl: AnimationCache { 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 + guard let writer = AnimationCacheItemWriterImpl(queue: self.fetchQueues[self.nextFetchQueueIndex % 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 @@ -347,13 +748,18 @@ 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 + } + let _ = try? FileManager.default.removeItem(atPath: itemFirstFramePath) + guard let _ = try? FileManager.default.moveItem(atPath: result.firstFramePath, toPath: itemFirstFramePath) else { return } guard let item = loadItem(path: itemPath) else { @@ -368,9 +774,14 @@ public final class AnimationCacheImpl: AnimationCache { return EmptyDisposable } - let fetchDisposable = fetch(size, 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() }) } @@ -389,25 +800,43 @@ public final class AnimationCacheImpl: AnimationCache { } } - func getSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? { + static func getFirstFrameSynchronously(basePath: String, sourceId: String, size: CGSize) -> AnimationCacheItem? { let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId + "-\(Int(size.width))x\(Int(size.height))")) - let itemDirectoryPath = "\(self.basePath)/\(sourceIdPath.directory)" - let itemPath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)" + let itemDirectoryPath = "\(basePath)/\(sourceIdPath.directory)" + let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" - if FileManager.default.fileExists(atPath: itemPath) { - return loadItem(path: itemPath) + if FileManager.default.fileExists(atPath: itemFirstFramePath) { + return loadItem(path: itemFirstFramePath) } else { return nil } } + + static func getFirstFrame(basePath: String, sourceId: String, size: CGSize, completion: @escaping (AnimationCacheItem?) -> Void) -> Disposable { + let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId + "-\(Int(size.width))x\(Int(size.height))")) + let itemDirectoryPath = "\(basePath)/\(sourceIdPath.directory)" + let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" + + if FileManager.default.fileExists(atPath: itemFirstFramePath), let item = loadItem(path: itemFirstFramePath) { + completion(item) + + return EmptyDisposable + } else { + completion(nil) + + return EmptyDisposable + } + } } private let queue: Queue + private let basePath: String private let impl: QueueLocalObject public init(basePath: String, allocateTempFile: @escaping () -> String) { let queue = Queue() self.queue = queue + self.basePath = basePath self.impl = QueueLocalObject(queue: queue, generate: { return Impl(queue: queue, basePath: basePath, allocateTempFile: allocateTempFile) }) @@ -431,9 +860,18 @@ public final class AnimationCacheImpl: AnimationCache { |> runOn(self.queue) } - public func getSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? { - return self.impl.syncWith { impl -> AnimationCacheItem? in - return impl.getSynchronously(sourceId: sourceId, size: size) + public func getFirstFrameSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? { + return Impl.getFirstFrameSynchronously(basePath: self.basePath, sourceId: sourceId, size: size) + } + + public func getFirstFrame(queue: Queue, sourceId: String, size: CGSize, completion: @escaping (AnimationCacheItem?) -> Void) -> Disposable { + let disposable = MetaDisposable() + + let basePath = self.basePath + queue.async { + disposable.set(Impl.getFirstFrame(basePath: basePath, sourceId: sourceId, size: size, 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..a30d8fd48f --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -0,0 +1,231 @@ +import Foundation +import UIKit +import DCT + +final class ImagePlane { + let width: Int + let height: Int + let bytesPerRow: Int + let components: Int + var data: Data + + init(width: Int, height: Int, components: Int) { + self.width = width + self.height = height + self.bytesPerRow = width * components + self.components = components + self.data = Data(count: width * components * height) + } +} + +final class ImageARGB { + let argbPlane: ImagePlane + + init(width: Int, height: Int) { + self.argbPlane = ImagePlane(width: width, height: height, components: 4) + } +} + +final class ImageYUVA420 { + let yPlane: ImagePlane + let uPlane: ImagePlane + let vPlane: ImagePlane + let aPlane: ImagePlane + + init(width: Int, height: Int) { + self.yPlane = ImagePlane(width: width, height: height, components: 1) + self.uPlane = ImagePlane(width: width / 2, height: height / 2, components: 1) + self.vPlane = ImagePlane(width: width / 2, height: height / 2, components: 1) + self.aPlane = ImagePlane(width: width, height: height, components: 1) + } +} + +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() -> ImageYUVA420 { + let resultImage = ImageYUVA420(width: self.argbPlane.width, height: self.argbPlane.height) + 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() -> ImageARGB { + let resultImage = ImageARGB(width: self.yPlane.width, height: self.yPlane.height) + self.toARGB(target: resultImage) + return resultImage + } +} + +final class DctData { + let quality: Int + let dctData: Data + let idctData: Data + + init(quality: Int) { + self.quality = quality + self.dctData = generateForwardDctData(Int32(quality))! + self.idctData = generateInverseDctData(Int32(quality))! + } +} + +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 + switch i { + case 0: + sourcePlane = self.yPlane + targetPlane = target.yPlane + case 1: + sourcePlane = self.uPlane + targetPlane = target.uPlane + case 2: + sourcePlane = self.vPlane + targetPlane = target.vPlane + case 3: + sourcePlane = self.aPlane + targetPlane = target.aPlane + 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: UInt16.self) + + performForwardDct(sourcePixels, coefficients, Int32(sourcePlane.width), Int32(sourcePlane.height), Int32(sourcePlane.bytesPerRow), dctData.dctData) + } + } + } + } + + 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 + switch i { + case 0: + sourcePlane = self.yPlane + targetPlane = target.yPlane + case 1: + sourcePlane = self.uPlane + targetPlane = target.uPlane + case 2: + sourcePlane = self.vPlane + targetPlane = target.vPlane + case 3: + sourcePlane = self.aPlane + targetPlane = target.aPlane + default: + preconditionFailure() + } + + sourcePlane.data.withUnsafeBytes { sourceBytes in + let coefficients = sourceBytes.baseAddress!.assumingMemoryBound(to: UInt16.self) + + targetPlane.data.withUnsafeMutableBytes { bytes in + let pixels = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self) + + performInverseDct(coefficients, pixels, Int32(sourcePlane.width), Int32(sourcePlane.height), Int32(targetPlane.bytesPerRow), Int32(sourcePlane.width), dctData.idctData) + } + } + } + } + + func idct(dctData: DctData) -> ImageYUVA420 { + let resultImage = ImageYUVA420(width: self.yPlane.width, height: self.yPlane.height) + self.idct(dctData: dctData, target: resultImage) + return resultImage + } +} 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 051259f600..eecc39922f 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -11,25 +11,39 @@ 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 groupId: String + 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 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 +53,36 @@ 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, groupId: String, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { + self.context = context + self.groupId = groupId + self.emoji = emoji + self.cache = cache + self.renderer = renderer + self.placeholderColor = placeholderColor + + let scale = min(2.0, UIScreenScale) + self.pointSize = CGSize(width: 24, height: 24) + self.pixelSize = CGSize(width: self.pointSize.width * scale, height: self.pointSize.height * scale) super.init() - let scale = min(2.0, UIScreenScale) - let pixelSize = CGSize(width: 24 * scale, height: 24 * scale) - - if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { - let size = CGSize(width: pixelSize.width / scale, height: pixelSize.height / scale) - 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.infoDisposable = (context.engine.stickers.loadedStickerPack(reference: emoji.stickerPack, forceActualized: false) + |> deliverOnMainQueue).start(next: { [weak self] result in + guard let strongSelf = self else { + return } - } - - self.disposable = renderer.add(groupId: groupId, target: self, 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 + switch result { + case let .result(_, items, _): + for item in items { + if item.file.fileId.id == emoji.fileId { + strongSelf.updateFile(file: item.file, attemptSynchronousLoad: false) + break + } } - - 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 = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)).start() - - return ActionDisposable { - dataDisposable.dispose() - fetchDisposable.dispose() + default: + break } }) } @@ -91,6 +96,8 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } deinit { + self.loadDisposable?.dispose() + self.infoDisposable?.dispose() self.disposable?.dispose() self.fetchDisposable?.dispose() } @@ -110,13 +117,70 @@ 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(groupId: self.groupId, 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.loadAnimation() + } else { + self.loadDisposable = self.renderer.loadFirstFrame(groupId: self.groupId, target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, completion: { [weak self] _ in + self?.loadAnimation() + }) + self.loadAnimation() + } + } + + private func loadAnimation() { + guard let file = self.file else { + return + } + + let context = self.context + self.disposable = renderer.add(groupId: self.groupId, 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.isVideoSticker { + 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: stickerPackFileReference(file), resource: file.resource).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() + } + }) + } } 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, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { + self.contentLayer = InlineStickerItemLayer(context: context, groupId: "textInputView", attemptSynchronousLoad: true, emoji: emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor) super.init(frame: CGRect()) @@ -131,6 +195,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/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index f8ed135071..5c03454d8a 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -301,6 +301,39 @@ public final class EmojiPagerContentComponent: Component { super.init() if file.isAnimatedSticker || file.isVideoSticker { + let loadAnimation: () -> Void = { [weak self] in + guard let strongSelf = self else { + return + } + + strongSelf.disposable = renderer.add(groupId: groupId, 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.isVideoSticker { + 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: stickerPackFileReference(file), resource: file.resource).start() + + return ActionDisposable { + dataDisposable.dispose() + fetchDisposable.dispose() + } + }) + } + if attemptSynchronousLoad { if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { self.displayPlaceholder = true @@ -309,34 +342,13 @@ public final class EmojiPagerContentComponent: Component { self.contents = image.cgImage } } - } - - self.disposable = renderer.add(groupId: groupId, target: self, 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.isVideoSticker { - 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) - } + loadAnimation() + } else { + let _ = renderer.loadFirstFrame(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { _ in + loadAnimation() }) - - let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: file.resource).start() - - return ActionDisposable { - dataDisposable.dispose() - fetchDisposable.dispose() - } - }) + } } else if let dimensions = file.dimensions { let isSmall: Bool = false self.disposable = (chatMessageSticker(account: context.account, file: file, small: isSmall, synchronousLoad: attemptSynchronousLoad)).start(next: { [weak self] resultTransform in @@ -588,7 +600,7 @@ public final class EmojiPagerContentComponent: Component { if let current = self.visibleItemLayers[itemId] { itemLayer = current } else { - itemLayer = ItemLayer(item: item, context: component.context, groupId: "keyboard", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, cache: component.animationCache, renderer: component.animationRenderer, placeholderColor: theme.chat.inputMediaPanel.stickersBackgroundColor, pointSize: CGSize(width: itemLayout.itemSize, height: itemLayout.itemSize)) + itemLayer = ItemLayer(item: item, context: component.context, groupId: "keyboard", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, cache: component.animationCache, renderer: component.animationRenderer, placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), pointSize: CGSize(width: itemLayout.itemSize, height: itemLayout.itemSize)) self.scrollView.layer.addSublayer(itemLayer) self.visibleItemLayers[itemId] = itemLayer } diff --git a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift index 1049ce1d21..a3f4e96a63 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift +++ b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift @@ -6,18 +6,23 @@ import RLottieBinding import GZip 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 frameDuration = 1.0 / Double(animation.frameRate) + for i in 0 ..< animation.frameCount { + 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)) + }, proposedWidth: width, proposedHeight: height, duration: frameDuration) + } + 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/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index d399ea98cc..c952603feb 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -7,6 +7,7 @@ import AnimationCache public protocol MultiAnimationRenderer: AnyObject { func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool + func loadFirstFrame(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable } open class MultiAnimationRenderTarget: SimpleLayer { @@ -48,43 +49,19 @@ private func convertFrameToImage(frame: AnimationCacheItemFrame) -> UIImage? { private final class FrameGroup { let image: UIImage let size: CGSize - let frameRange: Range - let count: Int - let skip: Int + let timestamp: Double - 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 { + init?(item: AnimationCacheItem, timestamp: Double) { + guard let firstFrame = item.getFrame(at: timestamp) 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 context = DrawingContext(size: CGSize(width: CGFloat(width), height: CGFloat(height)), scale: 1.0, opaque: false, bytesPerRow: bytesPerRow) - 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) - } + firstFrame.data.withUnsafeBytes { bytes -> Void in + memcpy(context.bytes, bytes.baseAddress!.advanced(by: firstFrame.range.lowerBound), height * bytesPerRow) } guard let image = context.generateImage() else { @@ -93,22 +70,9 @@ private final class FrameGroup { self.image = image self.size = CGSize(width: CGFloat(width), height: CGFloat(height)) - self.frameRange = baseFrameIndex ..< (baseFrameIndex + count) - self.count = count - self.skip = skip + self.timestamp = timestamp } } - - 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)) - } } private final class LoadFrameGroupTask { @@ -127,9 +91,8 @@ private final class ItemAnimationContext { private var disposable: Disposable? private var displayLink: ConstantDisplayLinkAnimator? - private var frameIndex: Int = 0 + private var timestamp: Double = 0.0 private var item: AnimationCacheItem? - private var frameSkip: Int private var currentFrameGroup: FrameGroup? private var isLoadingFrameGroup: Bool = false @@ -144,9 +107,8 @@ private final class ItemAnimationContext { let targets = Bag>() - init(cache: AnimationCache, itemId: String, size: CGSize, frameSkip: Int, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { + init(cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { self.cache = cache - self.frameSkip = frameSkip self.stateUpdated = stateUpdated self.disposable = cache.get(sourceId: itemId, size: size, fetch: fetch).start(next: { [weak self] result in @@ -174,14 +136,9 @@ 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.updateDisplayPlaceholder(displayPlaceholder: false) - target.contents = currentFrameGroup.image.cgImage - target.contentsRect = contentsRect - } + if let currentFrameGroup = self.currentFrameGroup { + target.updateDisplayPlaceholder(displayPlaceholder: false) + target.contents = currentFrameGroup.image.cgImage } self.updateIsPlaying() @@ -209,27 +166,26 @@ 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 + let timestamp = self.timestamp + if let advanceTimestamp = advanceTimestamp { + self.timestamp += advanceTimestamp + } - if let currentFrameGroup = self.currentFrameGroup, currentFrameGroup.frameRange.contains(currentFrame) { + if let currentFrameGroup = self.currentFrameGroup, currentFrameGroup.timestamp == self.timestamp { } 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) + let currentFrameGroup = FrameGroup(item: item, timestamp: timestamp) return { guard let strongSelf = self else { @@ -241,24 +197,20 @@ private final class ItemAnimationContext { if let currentFrameGroup = currentFrameGroup { strongSelf.currentFrameGroup = currentFrameGroup for target in strongSelf.targets.copyItems() { - target.value?.contents = currentFrameGroup.image.cgImage + if let target = target.value { + target.contents = currentFrameGroup.image.cgImage + target.updateDisplayPlaceholder(displayPlaceholder: false) + } } - - let _ = strongSelf.update(advanceFrame: false) } } }) } - if advanceFrame { - self.frameIndex += self.frameSkip - } - - if let currentFrameGroup = self.currentFrameGroup, let contentsRect = currentFrameGroup.contentsRect(index: currentFrame) { + if let _ = self.currentFrameGroup { for target in self.targets.copyItems() { if let target = target.value { target.updateDisplayPlaceholder(displayPlaceholder: false) - target.contentsRect = contentsRect } } } @@ -269,7 +221,7 @@ private final class ItemAnimationContext { public final class MultiAnimationRendererImpl: MultiAnimationRenderer { private final class GroupContext { - private var frameSkip: Int + private let firstFrameQueue: Queue private let stateUpdated: () -> Void private var itemContexts: [String: ItemAnimationContext] = [:] @@ -282,8 +234,8 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - init(frameSkip: Int, stateUpdated: @escaping () -> Void) { - self.frameSkip = frameSkip + init(firstFrameQueue: Queue, stateUpdated: @escaping () -> Void) { + self.firstFrameQueue = firstFrameQueue self.stateUpdated = stateUpdated } @@ -292,7 +244,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { 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 + itemContext = ItemAnimationContext(cache: cache, itemId: itemId, size: size, fetch: fetch, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -339,8 +291,8 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } 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 { + if let item = cache.getFirstFrameSynchronously(sourceId: itemId, size: size) { + guard let frameGroup = FrameGroup(item: item, timestamp: 0.0) else { return false } @@ -352,6 +304,33 @@ 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 frameGroup = FrameGroup(item: item, timestamp: 0.0) + + Queue.mainQueue().async { + guard let target = target else { + completion(false) + return + } + if let frameGroup = frameGroup { + target.contents = frameGroup.image.cgImage + + completion(true) + } else { + completion(false) + } + } + }) + } + private func updateIsPlaying() { var isPlaying = false for (_, itemContext) in self.itemContexts { @@ -364,11 +343,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) } } @@ -378,6 +357,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } + private let firstFrameQueue: Queue private var groupContexts: [String: GroupContext] = [:] private var frameSkip: Int private var displayLink: ConstantDisplayLinkAnimator? @@ -407,6 +387,8 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } public init() { + self.firstFrameQueue = Queue(name: "MultiAnimationRenderer-FirstFrame", qos: .userInteractive) + if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.activeProcessorCount > 2 { self.frameSkip = 1 } else { @@ -419,7 +401,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { if let current = self.groupContexts[groupId] { groupContext = current } else { - groupContext = GroupContext(frameSkip: self.frameSkip, stateUpdated: { [weak self] in + groupContext = GroupContext(firstFrameQueue: self.firstFrameQueue, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -440,7 +422,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { if let current = self.groupContexts[groupId] { groupContext = current } else { - groupContext = GroupContext(frameSkip: self.frameSkip, stateUpdated: { [weak self] in + groupContext = GroupContext(firstFrameQueue: self.firstFrameQueue, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -452,6 +434,23 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { return groupContext.loadFirstFrameSynchronously(target: target, cache: cache, itemId: itemId, size: size) } + public func loadFirstFrame(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { + let groupContext: GroupContext + if let current = self.groupContexts[groupId] { + groupContext = current + } else { + groupContext = GroupContext(firstFrameQueue: self.firstFrameQueue, stateUpdated: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.updateIsPlaying() + }) + self.groupContexts[groupId] = 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 { @@ -464,11 +463,20 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { self.isPlaying = isPlaying } + private var previousTimestamp: Double? + private func animationTick() { + let timestamp = CFAbsoluteTimeGetCurrent() + if let _ = self.previousTimestamp { + } + self.previousTimestamp = timestamp + + let secondsPerFrame = Double(self.frameSkip) / 60.0 + var tasks: [LoadFrameGroupTask] = [] for (_, groupContext) in self.groupContexts { if groupContext.isPlaying { - tasks.append(contentsOf: groupContext.animationTick()) + tasks.append(contentsOf: groupContext.animationTick(advanceTimestamp: secondsPerFrame)) } } diff --git a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift index c052c0b77b..ddd56772f7 100644 --- a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift +++ b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift @@ -5,23 +5,46 @@ 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) { - let queue = Queue() - queue.async { - guard let frameSource = makeVideoStickerDirectFrameSource(queue: queue, path: path, width: width, height: height, cachePathPrefix: nil) else { + writer.queue.async { + guard let frameSource = makeVideoStickerDirectFrameSource(queue: writer.queue, path: path, width: roundUp(width, multiple: 16), height: roundUp(height, multiple: 16), cachePathPrefix: nil) else { return } let frameDuration = 1.0 / Double(frameSource.frameRate) while true { + if writer.isCancelled { + break + } if let frame = frameSource.takeFrame(draw: true) { - //AnimatedStickerFrame(data: frameData, type: .argb, width: self.width, height: self.height, bytesPerRow: self.bytesPerRow, index: frameIndex, isLastFrame: frameIndex == self.frameCount - 1, totalFrames: self.frameCount, multiplyAlpha: true) if case .argb = frame.type { - let frameWidth = frame.width - let frameHeight = frame.height let bytesPerRow = frame.bytesPerRow - frame.data.withUnsafeBytes { bytes -> Void in - writer.add(bytes: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), length: bytes.count, width: Int(frameWidth), height: Int(frameHeight), bytesPerRow: Int(bytesPerRow), duration: frameDuration) - } + + 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) + } + } + } + }, proposedWidth: frame.width, proposedHeight: frame.height, duration: frameDuration) } else { break } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index e891ae810d..5ee132edaf 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -8577,16 +8577,23 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, insertText: { [weak self] text in - guard let strongSelf = self else { + guard let strongSelf = self, let interfaceInteraction = strongSelf.interfaceInteraction else { return } if !strongSelf.chatDisplayNode.isTextInputPanelActive { return } - guard let textInputPanelNode = strongSelf.chatDisplayNode.textInputPanelNode else { - 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) } - textInputPanelNode.insertText(string: text) }, backwardsDeleteText: { [weak self] in guard let strongSelf = self else { return diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 8c9f9cd9fc..662db807d6 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -13,6 +13,7 @@ import Postbox import TelegramCore import ComponentDisplayAdapters import SettingsUI +import TextFormat final class ChatEntityKeyboardInputNode: ChatInputNode { struct InputData: Equatable { @@ -40,7 +41,24 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let interfaceInteraction = interfaceInteraction else { return } - interfaceInteraction.insertText(item.emoji) + var text = "." + var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? + loop: for attribute in item.file.attributes { + switch attribute { + case let .Sticker(displayText, packReference, _): + text = displayText + if let packReference = packReference { + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: item.file.fileId.id) + break loop + } + default: + break + } + } + + if let emojiAttribute = emojiAttribute { + interfaceInteraction.insertText(NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: emojiAttribute])) + } }, deleteBackwards: { [weak interfaceInteraction] in guard let interfaceInteraction = interfaceInteraction else { @@ -87,37 +105,33 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }) let animationRenderer = MultiAnimationRendererImpl() - let emojiItems: Signal = combineLatest( - context.engine.stickers.loadedStickerPack(reference: .animatedEmoji, forceActualized: false), - context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudSavedStickers)) - ) - |> map { animatedEmoji, savedStickers -> EmojiPagerContentComponent in + let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] + let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] + + let emojiItems: Signal = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000) + |> map { view -> EmojiPagerContentComponent in var emojiItems: [EmojiPagerContentComponent.Item] = [] - for item in savedStickers { - if let item = item.contents.get(SavedStickerItem.self) { - if item.file.isVideoSticker { - emojiItems.append(EmojiPagerContentComponent.Item( - emoji: "", - file: item.file - )) + var emojiCollectionIds = Set() + for (id, info, _) in view.collectionInfos { + if let info = info as? StickerPackCollectionInfo { + if info.shortName.lowercased().contains("emoji") { + emojiCollectionIds.insert(id) } } } - switch animatedEmoji { - case let .result(_, items, _): - for item in items { - if let emoji = item.getStringRepresentationsOfIndexKeys().first { - let strippedEmoji = emoji.basicEmoji.0.strippedEmoji - emojiItems.append(EmojiPagerContentComponent.Item( - emoji: strippedEmoji, - file: item.file - )) - } + for entry in view.entries { + guard let item = entry.item as? StickerPackItem else { + continue + } + if emojiCollectionIds.contains(entry.index.collectionId) { + let resultItem = EmojiPagerContentComponent.Item( + emoji: "", + file: item.file + ) + emojiItems.append(resultItem) } - default: - break } var itemGroups: [EmojiPagerContentComponent.ItemGroup] = [] @@ -145,8 +159,6 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } |> distinctUntilChanged - let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] - let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] let stickerItems: Signal = combineLatest( context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000), hasPremium diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 4bd4d9df65..b66b0bb07a 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -47,18 +47,18 @@ private final class CachedChatMessageText { } private final class InlineStickerItem: Hashable { - let file: TelegramMediaFile + let emoji: ChatTextInputTextCustomEmojiAttribute - init(file: TelegramMediaFile) { - self.file = file + init(emoji: ChatTextInputTextCustomEmojiAttribute) { + self.emoji = emoji } func hash(into hasher: inout Hasher) { - hasher.combine(self.file.fileId) + hasher.combine(emoji.fileId) } static func ==(lhs: InlineStickerItem, rhs: InlineStickerItem) -> Bool { - if lhs.file.fileId != rhs.file.fileId { + if lhs.emoji.fileId != rhs.emoji.fileId { return false } return true @@ -341,38 +341,26 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { 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[NSAttributedString.Key("Attribute__EmbeddedItem")] = InlineStickerItem(emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId)) - 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: "[\u{00a0}\u{00a0}\u{00a0}]", attributes: updatedAttributes) + updatedString.replaceCharacters(in: range, with: insertString) } attributedText = updatedString - }*/ + } let cutout: TextNodeCutout? = nil @@ -558,27 +546,27 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } private func updateInlineStickers(context: AccountContext, cache: AnimationCache, renderer: MultiAnimationRenderer, textLayout: TextNodeLayout?, placeholderColor: UIColor) { - var nextIndexById: [MediaId: Int] = [:] + 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.file.fileId] { + if let currentNext = nextIndexById[stickerItem.emoji.fileId] { index = currentNext } else { index = 0 } - nextIndexById[stickerItem.file.fileId] = index + 1 - let id = InlineStickerItemLayer.Key(id: stickerItem.file.fileId, index: index) + nextIndexById[stickerItem.emoji.fileId] = index + 1 + let id = InlineStickerItemLayer.Key(id: stickerItem.emoji.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) + itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor) self.inlineStickerItemLayers[id] = itemLayer self.textNode.layer.addSublayer(itemLayer) itemLayer.isVisibleForAnimations = self.isVisibleForAnimations diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index c4798cd366..59a51c5c83 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -244,6 +244,67 @@ 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(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) + } + } +} + class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let clippingNode: ASDisplayNode var textPlaceholderNode: ImmediateTextNode @@ -253,6 +314,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let textInputContainer: ASDisplayNode var textInputNode: EditableTextNode? var dustNode: InvisibleInkDustNode? + var customEmojiContainerView: CustomEmojiContainerView? let textInputBackgroundNode: ASImageNode private var transparentTextInputBackgroundImage: UIImage? @@ -463,7 +525,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { private var touchDownGestureRecognizer: TouchDownGestureRecognizer? - private var emojiViewProvider: ((String) -> UIView)? + private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? init(presentationInterfaceState: ChatPresentationInterfaceState, presentationContext: ChatPresentationContext?, presentController: @escaping (ViewController) -> Void) { self.presentationInterfaceState = presentationInterfaceState @@ -673,11 +735,11 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { 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)) + return EmojiTextAttachmentView(context: context, emoji: emoji, cache: presentationContext.animationCache, renderer: presentationContext.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12)) } } } @@ -1904,6 +1966,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let textColor = presentationInterfaceState.theme.chat.inputPanel.inputTextColor var rects: [CGRect] = [] + var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] if let attributedText = textInputNode.attributedText { let beginning = textInputNode.textView.beginningOfDocument @@ -1940,6 +2003,14 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let endIndex = currentIndex addSpoiler(startIndex: currentStartIndex, endIndex: endIndex) } + } else 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 + } + } } }) } @@ -1961,6 +2032,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(emojiRects: customEmojiRects) + } else if let customEmojiContainerView = self.customEmojiContainerView { + customEmojiContainerView.removeFromSuperview() + self.customEmojiContainerView = nil + } } private func updateSpoilersRevealed(animated: Bool = true) { @@ -2226,7 +2319,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } } - if mediaInputIsActive { + if mediaInputIsActive && !"".isEmpty { if self.actionButtons.expandMediaInputButton.alpha.isZero { self.actionButtons.expandMediaInputButton.alpha = 1.0 if animated { @@ -2727,13 +2820,6 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.textInputNode?.becomeFirstResponder() } - func insertText(string: String) { - guard let textInputNode = self.textInputNode else { - return - } - textInputNode.textView.insertText(string) - } - func backwardsDeleteText() { guard let textInputNode = self.textInputNode else { return diff --git a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift index f9dbd1d6e7..3bdae8b476 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,8 +18,9 @@ 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 func stateAttributedStringForText(_ text: NSAttributedString) -> NSAttributedString { @@ -28,7 +30,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 +66,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 +110,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) } } @@ -215,6 +219,26 @@ public final class ChatTextInputTextUrlAttribute: NSObject { } } +public final class ChatTextInputTextCustomEmojiAttribute: NSObject { + public let stickerPack: StickerPackReference + public let fileId: Int64 + + public init(stickerPack: StickerPackReference, fileId: Int64) { + self.stickerPack = stickerPack + self.fileId = fileId + + super.init() + } + + override public func isEqual(_ object: Any?) -> Bool { + if let other = object as? ChatTextInputTextCustomEmojiAttribute { + return self.stickerPack == other.stickerPack && self.fileId == other.fileId + } else { + return false + } + } +} + private func textUrlRangesEqual(_ lhs: [(NSRange, ChatTextInputTextUrlAttribute)], _ rhs: [(NSRange, ChatTextInputTextUrlAttribute)]) -> Bool { if lhs.count != rhs.count { return false @@ -459,7 +483,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 +517,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 +558,17 @@ 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) + if let emojiViewProvider = emojiViewProvider { + let _ = emojiViewProvider + /*let emojiText = attributedText.attributedSubstring(from: range) + let attachment = EmojiTextAttachment(index: emojiIndex, text: emojiText.string, emoji: value, viewProvider: emojiViewProvider) + emojiIndex += 1 + attachment.bounds = CGRect(origin: CGPoint(), size: CGSize(width: 26.0, height: 16.0)) + + replaceRanges.append((range, attachment))*/ + } } } @@ -556,12 +595,16 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme } } }) + + for (range, attachment) in replaceRanges.sorted(by: { $0.0.location > $1.0.location }) { + textNode.textView.textStorage.replaceCharacters(in: range, with: NSAttributedString(attachment: attachment)) + } } - if #available(iOS 15, *), let emojiViewProvider = emojiViewProvider { + if #available(iOS 15, *), let _ = emojiViewProvider { let _ = CustomTextAttachmentViewProvider.ensureRegistered - var nextIndex: [String: Int] = [:] + /*var nextIndex: [String: Int] = [:] var count = 0 @@ -572,7 +615,7 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme } }) - while count < 10 { + while count < 400 { 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 { @@ -601,11 +644,11 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme if !found { break } - } + }*/ } } -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 +945,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..2d6ebff158 100644 --- a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift +++ b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift @@ -40,6 +40,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), range: range) default: break } From 96a410fc143a2904219682a937357e72e1e6e62a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jun 2022 02:47:05 +0100 Subject: [PATCH 006/113] [Temp] Add debug option for the upgraded entity input panel --- .../Sources/AnimationCache.swift | 10 +++- .../Sources/ChatControllerNode.swift | 43 +++++++++++----- .../Sources/ChatEntityKeyboardInputNode.swift | 51 ++++++++++++++----- .../TelegramUI/Sources/ChatInputNode.swift | 2 +- .../Sources/ChatInterfaceInputNodes.swift | 2 +- 5 files changed, 78 insertions(+), 30 deletions(-) diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 2f6e8197d6..ddce377bf3 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -704,7 +704,15 @@ public final class AnimationCacheImpl: AnimationCache { init(queue: Queue, basePath: String, allocateTempFile: @escaping () -> String) { self.queue = queue - self.fetchQueues = (0 ..< 2).map { _ in Queue() } + + let fetchQueueCount: Int + if ProcessInfo.processInfo.activeProcessorCount > 2 { + fetchQueueCount = 4 + } else { + fetchQueueCount = 2 + } + + self.fetchQueues = (0 ..< fetchQueueCount).map { i in Queue(name: "AnimationCacheImpl-Fetch\(i)", qos: .default) } self.basePath = basePath self.allocateTempFile = allocateTempFile } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 873088a728..dad5427e80 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -912,11 +912,13 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if let inputNode = 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() }) { - /*if let inputPanelNode = self.inputPanelNode as? ChatTextInputPanelNode { - if inputPanelNode.isFocused { - self.context.sharedContext.mainWindow?.simulateKeyboardDismiss(transition: .animated(duration: 0.5, curve: .spring)) + 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 { self.inputMediaNode = inputMediaNode inputMediaNode.requestDisableStickerAnimations = { [weak self] disabled in @@ -934,11 +936,16 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputNode.alpha = 1.0 inputNode.layer.removeAnimation(forKey: "opacity") immediatelyLayoutInputNodeAndAnimateAppearance = true - /*if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { - self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: inputPanelNode) - } else {*/ - self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) - //} + + if self.inputMediaNode != nil { + if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: inputPanelNode) + } else { + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) + } + } else { + self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) + } if let externalTopPanelContainer = inputNode.externalTopPanelContainer { if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { @@ -2098,7 +2105,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputMediaNodeDataPromise.set(ChatEntityKeyboardInputNode.inputData(context: self.context, interfaceInteraction: interfaceInteraction, controllerInteraction: self.controllerInteraction)) } - if self.inputMediaNode == nil && !"".isEmpty { + if self.inputMediaNode == nil && !self.context.sharedContext.immediateExperimentalUISettings.inlineStickers { 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 { @@ -2522,9 +2529,19 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { }) } } else { - self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId({ state in - return (.media(mode: .other, expanded: nil, focused: false), state.interfaceState.messageActionsState.closedButtonKeyboardMessageId) - }) + 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) + }) + }) + } } } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 662db807d6..0fbdb124a7 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -110,7 +110,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let emojiItems: Signal = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000) |> map { view -> EmojiPagerContentComponent in - var emojiItems: [EmojiPagerContentComponent.Item] = [] + struct ItemGroup { + var id: AnyHashable + var items: [EmojiPagerContentComponent.Item] + } + var itemGroups: [ItemGroup] = [] + var itemGroupIndexById: [AnyHashable: Int] = [:] var emojiCollectionIds = Set() for (id, info, _) in view.collectionInfos { @@ -125,27 +130,45 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let item = entry.item as? StickerPackItem else { continue } - if emojiCollectionIds.contains(entry.index.collectionId) { - let resultItem = EmojiPagerContentComponent.Item( - emoji: "", - file: item.file - ) - emojiItems.append(resultItem) + if item.file.isAnimatedSticker || item.file.isVideoSticker { + if emojiCollectionIds.contains(entry.index.collectionId) { + let resultItem = EmojiPagerContentComponent.Item( + emoji: "", + file: item.file + ) + + let groupId = entry.index.collectionId + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + } + } } } - var itemGroups: [EmojiPagerContentComponent.ItemGroup] = [] - itemGroups.append(EmojiPagerContentComponent.ItemGroup( - id: "all", - title: nil, - items: emojiItems - )) return EmojiPagerContentComponent( context: context, animationCache: animationCache, animationRenderer: animationRenderer, inputInteraction: emojiInputInteraction, - itemGroups: itemGroups, + itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in + var title: String? + if group.id == AnyHashable("recent") { + //TODO:localize + title = "Recently Used".uppercased() + } else { + for (id, info, _) in view.collectionInfos { + if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { + title = info.title.uppercased() + break + } + } + } + + return EmojiPagerContentComponent.ItemGroup(id: group.id, title: title, items: group.items) + }, itemLayoutType: .compact ) } diff --git a/submodules/TelegramUI/Sources/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index ca1ebffaab..d365208a9f 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -13,7 +13,7 @@ class ChatInputNode: ASDisplayNode { var externalTopPanelContainer: UIView? - var topBackgroundExtension: CGFloat = 0.0 + var topBackgroundExtension: CGFloat = 41.0 var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> 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) { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift index a988e0bdc1..031c020cfa 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift @@ -12,7 +12,7 @@ func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: } switch chatPresentationInterfaceState.inputMode { case .media: - if "".isEmpty { + if context.sharedContext.immediateExperimentalUISettings.inlineStickers { if let currentNode = currentNode as? ChatEntityKeyboardInputNode { return currentNode } else if let inputMediaNode = inputMediaNode { From 2e71c1fa5ec073400aa8ed8ec7cd6963b5f1ff0f Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jun 2022 02:48:30 +0100 Subject: [PATCH 007/113] Fix fetch queue parallelization --- .../Components/AnimationCache/Sources/AnimationCache.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index ddce377bf3..96c6211985 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -748,7 +748,9 @@ public final class AnimationCacheImpl: AnimationCache { updateResult(AnimationCacheItemResult(item: nil, isFinal: false)) if beginFetch { - guard let writer = AnimationCacheItemWriterImpl(queue: self.fetchQueues[self.nextFetchQueueIndex % self.fetchQueues.count], allocateTempFile: self.allocateTempFile, completion: { [weak self, weak itemContext] result in + let fetchQueueIndex = self.nextFetchQueueIndex + self.nextFetchQueueIndex += 1 + 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 From 791502752368ef2cfa83d7b891a56103d93d0e49 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jun 2022 02:49:58 +0100 Subject: [PATCH 008/113] Decrease parallel queue count --- .../Components/AnimationCache/Sources/AnimationCache.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 96c6211985..4b03fb865c 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -707,7 +707,7 @@ public final class AnimationCacheImpl: AnimationCache { let fetchQueueCount: Int if ProcessInfo.processInfo.activeProcessorCount > 2 { - fetchQueueCount = 4 + fetchQueueCount = 3 } else { fetchQueueCount = 2 } From c1c63e5095e94eb45611fe05d2de50452472d6ae Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 24 Jun 2022 11:35:15 +0100 Subject: [PATCH 009/113] Refactor IndexSet to RangeSet --- .../AccountContext/Sources/FetchManager.swift | 3 +- .../Sources/FetchMediaUtils.swift | 11 +++---- .../Sources/DirectMediaImageCache.swift | 2 +- submodules/FetchManagerImpl/BUILD | 1 + .../Sources/FetchManagerImpl.swift | 30 ++++++++++--------- 5 files changed, 26 insertions(+), 21 deletions(-) diff --git a/submodules/AccountContext/Sources/FetchManager.swift b/submodules/AccountContext/Sources/FetchManager.swift index 1646bfef07..a01a4b66b6 100644 --- a/submodules/AccountContext/Sources/FetchManager.swift +++ b/submodules/AccountContext/Sources/FetchManager.swift @@ -3,6 +3,7 @@ import Postbox import TelegramCore import SwiftSignalKit import TelegramUIPreferences +import RangeSet public enum FetchManagerCategory: Int32 { case image @@ -151,7 +152,7 @@ public enum FetchManagerPriority: Comparable { public protocol FetchManager { var queue: Queue { get } - func interactivelyFetched(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, mediaReference: AnyMediaReference?, resourceReference: MediaResourceReference, ranges: IndexSet, statsCategory: MediaResourceStatsCategory, elevatedPriority: Bool, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal + func interactivelyFetched(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, mediaReference: AnyMediaReference?, resourceReference: MediaResourceReference, ranges: RangeSet, statsCategory: MediaResourceStatsCategory, elevatedPriority: Bool, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal func cancelInteractiveFetches(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, resource: MediaResource) func cancelInteractiveFetches(resourceId: String) func toggleInteractiveFetchPaused(resourceId: String, isPaused: Bool) diff --git a/submodules/AccountContext/Sources/FetchMediaUtils.swift b/submodules/AccountContext/Sources/FetchMediaUtils.swift index 64eea5d434..29bf1e3d89 100644 --- a/submodules/AccountContext/Sources/FetchMediaUtils.swift +++ b/submodules/AccountContext/Sources/FetchMediaUtils.swift @@ -4,6 +4,7 @@ import TelegramCore import Postbox import SwiftSignalKit import TelegramUIPreferences +import RangeSet public func freeMediaFileInteractiveFetched(account: Account, fileReference: FileMediaReference) -> Signal { return fetchedMediaResource(mediaBox: account.postbox.mediaBox, reference: fileReference.resourceReference(fileReference.media.resource)) @@ -12,7 +13,7 @@ public func freeMediaFileInteractiveFetched(account: Account, fileReference: Fil public func freeMediaFileInteractiveFetched(fetchManager: FetchManager, fileReference: FileMediaReference, priority: FetchManagerPriority) -> Signal { let file = fileReference.media let mediaReference = AnyMediaReference.standalone(media: fileReference.media) - return fetchManager.interactivelyFetched(category: fetchCategoryForFile(file), location: .chat(PeerId(0)), locationKey: .free, mediaReference: mediaReference, resourceReference: mediaReference.resourceReference(file.resource), ranges: IndexSet(integersIn: 0 ..< Int(Int64.max) as Range), statsCategory: statsCategoryForFileWithAttributes(file.attributes), elevatedPriority: false, userInitiated: false, priority: priority, storeToDownloadsPeerType: nil) + return fetchManager.interactivelyFetched(category: fetchCategoryForFile(file), location: .chat(PeerId(0)), locationKey: .free, mediaReference: mediaReference, resourceReference: mediaReference.resourceReference(file.resource), ranges: RangeSet(0 ..< Int64.max), statsCategory: statsCategoryForFileWithAttributes(file.attributes), elevatedPriority: false, userInitiated: false, priority: priority, storeToDownloadsPeerType: nil) } public func freeMediaFileResourceInteractiveFetched(account: Account, fileReference: FileMediaReference, resource: MediaResource) -> Signal { @@ -37,7 +38,7 @@ public func messageMediaFileInteractiveFetched(context: AccountContext, message: return messageMediaFileInteractiveFetched(fetchManager: context.fetchManager, messageId: message.id, messageReference: MessageReference(message), file: file, userInitiated: userInitiated, priority: .userInitiated) } -public func messageMediaFileInteractiveFetched(fetchManager: FetchManager, messageId: MessageId, messageReference: MessageReference, file: TelegramMediaFile, ranges: IndexSet = IndexSet(integersIn: 0 ..< Int(Int64.max) as Range), userInitiated: Bool, priority: FetchManagerPriority) -> Signal { +public func messageMediaFileInteractiveFetched(fetchManager: FetchManager, messageId: MessageId, messageReference: MessageReference, file: TelegramMediaFile, ranges: RangeSet = RangeSet(0 ..< Int64.max), userInitiated: Bool, priority: FetchManagerPriority) -> Signal { let mediaReference = AnyMediaReference.message(message: messageReference, media: file) return fetchManager.interactivelyFetched(category: fetchCategoryForFile(file), location: .chat(messageId.peerId), locationKey: .messageId(messageId), mediaReference: mediaReference, resourceReference: mediaReference.resourceReference(file.resource), ranges: ranges, statsCategory: statsCategoryForFileWithAttributes(file.attributes), elevatedPriority: false, userInitiated: userInitiated, priority: priority, storeToDownloadsPeerType: nil) } @@ -52,11 +53,11 @@ public func messageMediaImageInteractiveFetched(context: AccountContext, message public func messageMediaImageInteractiveFetched(fetchManager: FetchManager, messageId: MessageId, messageReference: MessageReference, image: TelegramMediaImage, resource: MediaResource, range: Range? = nil, userInitiated: Bool, priority: FetchManagerPriority, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal { let mediaReference = AnyMediaReference.message(message: messageReference, media: image) - let ranges: IndexSet + let ranges: RangeSet if let range = range { - ranges = IndexSet(integersIn: Int(range.lowerBound) ..< Int(range.upperBound)) + ranges = RangeSet(range.lowerBound ..< range.upperBound) } else { - ranges = IndexSet(integersIn: Int(0) ..< Int(Int64.max)) + ranges = RangeSet(0 ..< Int64.max) } return fetchManager.interactivelyFetched(category: .image, location: .chat(messageId.peerId), locationKey: .messageId(messageId), mediaReference: mediaReference, resourceReference: mediaReference.resourceReference(resource), ranges: ranges, statsCategory: .image, elevatedPriority: false, userInitiated: userInitiated, priority: priority, storeToDownloadsPeerType: storeToDownloadsPeerType) } diff --git a/submodules/DirectMediaImageCache/Sources/DirectMediaImageCache.swift b/submodules/DirectMediaImageCache/Sources/DirectMediaImageCache.swift index 975d030fef..0b71087ed0 100644 --- a/submodules/DirectMediaImageCache/Sources/DirectMediaImageCache.swift +++ b/submodules/DirectMediaImageCache/Sources/DirectMediaImageCache.swift @@ -199,7 +199,7 @@ public final class DirectMediaImageCache { ).start() let dataSignal: Signal - if resourceSizeLimit < Int(Int64.max) { + if resourceSizeLimit < Int64.max { dataSignal = self.account.postbox.mediaBox.resourceData(resource.resource, size: resourceSizeLimit, in: 0 ..< resourceSizeLimit) |> map { data, _ -> Data? in return data diff --git a/submodules/FetchManagerImpl/BUILD b/submodules/FetchManagerImpl/BUILD index 93a7be74c7..2838c3104c 100644 --- a/submodules/FetchManagerImpl/BUILD +++ b/submodules/FetchManagerImpl/BUILD @@ -16,6 +16,7 @@ swift_library( "//submodules/TelegramUIPreferences:TelegramUIPreferences", "//submodules/AccountContext:AccountContext", "//submodules/MediaPlayer:UniversalMediaPlayer", + "//submodules/Utils/RangeSet:RangeSet", ], visibility = [ "//visibility:public", diff --git a/submodules/FetchManagerImpl/Sources/FetchManagerImpl.swift b/submodules/FetchManagerImpl/Sources/FetchManagerImpl.swift index 7308111946..c998542496 100644 --- a/submodules/FetchManagerImpl/Sources/FetchManagerImpl.swift +++ b/submodules/FetchManagerImpl/Sources/FetchManagerImpl.swift @@ -6,6 +6,7 @@ import Postbox import TelegramUIPreferences import AccountContext import UniversalMediaPlayer +import RangeSet public struct FetchManagerLocationEntryId: Hashable { public let location: FetchManagerLocation @@ -41,15 +42,15 @@ private final class FetchManagerLocationEntry { var userInitiated: Bool = false var storeToDownloadsPeerType: MediaAutoDownloadPeerType? let references = Bag() - let ranges = Bag() + let ranges = Bag>() var elevatedPriorityReferenceCount: Int32 = 0 var userInitiatedPriorityIndices: [Int32] = [] var isPaused: Bool = false - var combinedRanges: IndexSet { - var result = IndexSet() + var combinedRanges: RangeSet { + var result = RangeSet() if self.userInitiated { - result.insert(integersIn: 0 ..< Int(Int64.max)) + result.insert(contentsOf: 0 ..< Int64.max) } else { for range in self.ranges.copyItems() { result.formUnion(range) @@ -77,7 +78,7 @@ private final class FetchManagerLocationEntry { private final class FetchManagerActiveContext { let userInitiated: Bool - var ranges = IndexSet() + var ranges = RangeSet() var disposable: Disposable? init(userInitiated: Bool) { @@ -224,12 +225,13 @@ private final class FetchManagerCategoryContext { let entryCompleted = self.entryCompleted let storeManager = self.storeManager let parsedRanges: [(Range, MediaBoxFetchPriority)]? - if ranges.count == 1 && ranges.min() == 0 && ranges.max() == Int(Int64.max) { + + if ranges == RangeSet(0 ..< Int64.max) { parsedRanges = nil } else { var resultRanges: [(Range, MediaBoxFetchPriority)] = [] - for range in ranges.rangeView { - resultRanges.append((Int64(range.lowerBound) ..< Int64(range.upperBound), .default)) + for range in ranges.ranges { + resultRanges.append((range, .default)) } parsedRanges = resultRanges } @@ -312,14 +314,14 @@ private final class FetchManagerCategoryContext { var count = 0 var isCompleteRange = false var isVideoPreload = false - for range in ranges.rangeView { + for range in ranges.ranges { count += 1 - if range.lowerBound == 0 && range.upperBound == Int(Int64.max) { + if range.lowerBound == 0 && range.upperBound == Int64.max { isCompleteRange = true } } - if count == 2, let range = ranges.rangeView.first, range.lowerBound == 0 && range.upperBound == 2 * 1024 * 1024 { + if count == 2, let range = ranges.ranges.first, range.lowerBound == 0 && range.upperBound == 2 * 1024 * 1024 { isVideoPreload = true } @@ -327,8 +329,8 @@ private final class FetchManagerCategoryContext { parsedRanges = nil } else { var resultRanges: [(Range, MediaBoxFetchPriority)] = [] - for range in ranges.rangeView { - resultRanges.append((Int64(range.lowerBound) ..< Int64(range.upperBound), .default)) + for range in ranges.ranges { + resultRanges.append((range, .default)) } parsedRanges = resultRanges } @@ -709,7 +711,7 @@ public final class FetchManagerImpl: FetchManager { } } - public func interactivelyFetched(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, mediaReference: AnyMediaReference?, resourceReference: MediaResourceReference, ranges: IndexSet, statsCategory: MediaResourceStatsCategory, elevatedPriority: Bool, userInitiated: Bool, priority: FetchManagerPriority = .userInitiated, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal { + public func interactivelyFetched(category: FetchManagerCategory, location: FetchManagerLocation, locationKey: FetchManagerLocationKey, mediaReference: AnyMediaReference?, resourceReference: MediaResourceReference, ranges: RangeSet, statsCategory: MediaResourceStatsCategory, elevatedPriority: Bool, userInitiated: Bool, priority: FetchManagerPriority = .userInitiated, storeToDownloadsPeerType: MediaAutoDownloadPeerType?) -> Signal { let queue = self.queue return Signal { [weak self] subscriber in if let strongSelf = self { From 4e21428c101a039fb3bee2c30fc58e7339a707bc Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 24 Jun 2022 20:20:27 +0500 Subject: [PATCH 010/113] Fix particles animation --- .../PremiumUI/Sources/FasterStarsView.swift | 87 ++++++++++++------- 1 file changed, 58 insertions(+), 29 deletions(-) diff --git a/submodules/PremiumUI/Sources/FasterStarsView.swift b/submodules/PremiumUI/Sources/FasterStarsView.swift index f80b621f70..a96b632a1f 100644 --- a/submodules/PremiumUI/Sources/FasterStarsView.swift +++ b/submodules/PremiumUI/Sources/FasterStarsView.swift @@ -3,6 +3,7 @@ import UIKit import SceneKit import Display import AppBundle +import LegacyComponents final class FasterStarsView: UIView, PhoneDemoDecorationView { private let sceneView: SCNView @@ -55,23 +56,37 @@ final class FasterStarsView: UIView, PhoneDemoDecorationView { } self.playing = true - let speedAnimation = CABasicAnimation(keyPath: "speedFactor") - speedAnimation.fromValue = 1.0 - speedAnimation.toValue = 1.8 + let speedAnimation = POPBasicAnimation() + speedAnimation.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) + speedAnimation.fromValue = 1.0 as NSNumber + speedAnimation.toValue = 3.0 as NSNumber + speedAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) speedAnimation.duration = 0.8 - speedAnimation.fillMode = .forwards - particles.addAnimation(speedAnimation, forKey: "speedFactor") + particles.pop_add(speedAnimation, forKey: "speedFactor") - particles.speedFactor = 3.0 - - let stretchAnimation = CABasicAnimation(keyPath: "stretchFactor") - stretchAnimation.fromValue = 0.05 - stretchAnimation.toValue = 0.3 + let stretchAnimation = POPBasicAnimation() + stretchAnimation.property = (POPAnimatableProperty.property(withName: "stretchFactor", initializer: { property in + property?.readBlock = { particleSystem, values in + values?.pointee = (particleSystem as! SCNParticleSystem).stretchFactor + } + property?.writeBlock = { particleSystem, values in + (particleSystem as! SCNParticleSystem).stretchFactor = values!.pointee + } + property?.threshold = 0.01 + }) as! POPAnimatableProperty) + stretchAnimation.fromValue = 0.05 as NSNumber + stretchAnimation.toValue = 0.3 as NSNumber + stretchAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) stretchAnimation.duration = 0.8 - stretchAnimation.fillMode = .forwards - particles.addAnimation(stretchAnimation, forKey: "stretchFactor") - - particles.stretchFactor = 0.3 + particles.pop_add(stretchAnimation, forKey: "stretchFactor") } func resetAnimation() { @@ -79,24 +94,38 @@ final class FasterStarsView: UIView, PhoneDemoDecorationView { return } self.playing = false - - let speedAnimation = CABasicAnimation(keyPath: "speedFactor") - speedAnimation.fromValue = 3.0 - speedAnimation.toValue = 1.0 + + let speedAnimation = POPBasicAnimation() + speedAnimation.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) + speedAnimation.fromValue = 3.0 as NSNumber + speedAnimation.toValue = 1.0 as NSNumber + speedAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) speedAnimation.duration = 0.35 - speedAnimation.fillMode = .forwards - particles.addAnimation(speedAnimation, forKey: "speedFactor") + particles.pop_add(speedAnimation, forKey: "speedFactor") - particles.speedFactor = 1.0 - - let stretchAnimation = CABasicAnimation(keyPath: "stretchFactor") - stretchAnimation.fromValue = 0.3 - stretchAnimation.toValue = 0.05 + let stretchAnimation = POPBasicAnimation() + stretchAnimation.property = (POPAnimatableProperty.property(withName: "stretchFactor", initializer: { property in + property?.readBlock = { particleSystem, values in + values?.pointee = (particleSystem as! SCNParticleSystem).stretchFactor + } + property?.writeBlock = { particleSystem, values in + (particleSystem as! SCNParticleSystem).stretchFactor = values!.pointee + } + property?.threshold = 0.01 + }) as! POPAnimatableProperty) + stretchAnimation.fromValue = 0.3 as NSNumber + stretchAnimation.toValue = 0.05 as NSNumber + stretchAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) stretchAnimation.duration = 0.35 - stretchAnimation.fillMode = .forwards - particles.addAnimation(stretchAnimation, forKey: "stretchFactor") - - particles.stretchFactor = 0.05 + particles.pop_add(stretchAnimation, forKey: "stretchFactor") } override func layoutSubviews() { From 1c07c18f154887f5ac2e3cb0b65432be936d3ff9 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 24 Jun 2022 20:22:28 +0500 Subject: [PATCH 011/113] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 69 +- .../AccountUtils/Sources/AccountUtils.swift | 1 + submodules/BuildConfig/BUILD | 2 - .../PublicHeaders/BuildConfig/BuildConfig.h | 1 - submodules/BuildConfig/Sources/BuildConfig.m | 4 - submodules/CheckNode/Sources/CheckNode.swift | 9 + .../Source/Components/RoundedRectangle.swift | 26 +- .../Sources/InAppPurchaseManager.swift | 69 +- .../Sources/InviteLinkHeaderItem.swift | 49 +- .../Sources/IncreaseLimitFooterItem.swift | 2 +- submodules/PremiumUI/BUILD | 2 +- submodules/PremiumUI/Resources/gift.scn | Bin 0 -> 30009 bytes .../PremiumUI/Sources/DataRainView.swift | 4 - .../Sources/GiftAvatarComponent.swift | 294 ++++ .../PremiumUI/Sources/PremiumGiftScreen.swift | 1286 +++++++++++++++++ .../Sources/PremiumIntroScreen.swift | 132 +- .../Sources/PremiumStarComponent.swift | 2 +- .../PremiumUI/Sources/ScrollComponent.swift | 132 ++ submodules/SettingsUI/BUILD | 1 + .../Sources/DeleteAccountDataController.swift | 190 +++ .../Sources/DeleteAccountFooterItem.swift | 152 ++ .../DeleteAccountOptionsController.swift | 349 +++++ .../PresentationResourcesSettings.swift | 5 + .../Context Menu/Gift.imageset/Contents.json | 12 + .../Chat/Context Menu/Gift.imageset/gift.pdf | 512 +++++++ .../Menu/ClearSynced.imageset/Contents.json | 12 + .../Menu/ClearSynced.imageset/clearsynced.pdf | 136 ++ .../DeleteAddAccount.imageset/Contents.json | 12 + .../DeleteAddAccount.imageset/addaccount.pdf | 102 ++ .../Menu/DeleteChats.imageset/Contents.json | 12 + .../Menu/DeleteChats.imageset/deletechats.pdf | 175 +++ .../TelegramUI/Sources/AccountContext.swift | 7 +- .../TelegramUI/Sources/AppDelegate.swift | 2 +- .../Sources/ChatMessageDateHeader.swift | 16 + .../Sources/NotificationContentContext.swift | 2 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 192 +-- .../Sources/ShareExtensionContext.swift | 2 +- .../Sources/SharedAccountContext.swift | 6 +- 38 files changed, 3707 insertions(+), 274 deletions(-) create mode 100644 submodules/PremiumUI/Resources/gift.scn create mode 100644 submodules/PremiumUI/Sources/GiftAvatarComponent.swift create mode 100644 submodules/PremiumUI/Sources/PremiumGiftScreen.swift create mode 100644 submodules/PremiumUI/Sources/ScrollComponent.swift create mode 100644 submodules/SettingsUI/Sources/DeleteAccountDataController.swift create mode 100644 submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift create mode 100644 submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/gift.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/clearsynced.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/addaccount.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/deletechats.pdf diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 4f2eeb4d95..5e39ed1472 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -868,7 +868,6 @@ "MessageTimer.Years_2" = "%@ years"; "MessageTimer.Years_3_10" = "%@ years"; "MessageTimer.Years_any" = "%@ years"; -"MessageTimer.Months_many" = "%@ years"; "MessageTimer.ShortSeconds_1" = "%@s"; "MessageTimer.ShortSeconds_2" = "%@s"; @@ -7725,7 +7724,6 @@ Sorry for the inconvenience."; "Premium.Restore.Success" = "Done"; "Premium.Restore.ErrorUnknown" = "An error occurred. Please try again."; - "Settings.Premium" = "Telegram Premium"; "Settings.AddAnotherAccount.PremiumHelp" = "You can add up to four accounts with different phone numbers."; @@ -7735,3 +7733,70 @@ Sorry for the inconvenience."; "Appearance.AppIconPremium" = "Premium"; "Appearance.AppIconBlack" = "Black"; "Appearance.AppIconTurbo" = "Turbo"; + +"PrivacySettings.DeleteAccountNow" = "Delete Account Now"; + +"DeleteAccount.AlternativeOptionsTitle" = "Alternative Options"; + +"DeleteAccount.Options.ChangePhoneNumberTitle" = "Change Phone Number"; +"DeleteAccount.Options.ChangePhoneNumberText" = "Move your contacts, chats and media to a new number."; + +"DeleteAccount.Options.AddAccountTitle" = "Add Another Account"; +"DeleteAccount.Options.AddAccountText" = "You can use up to 3 accounts in one app at the same time."; +"DeleteAccount.Options.AddAccountPremiumText" = "You can use up to 4 accounts in one app at the same time."; + +"DeleteAccount.Options.ChangePrivacyTitle" = "Change Your Privacy Settings"; +"DeleteAccount.Options.ChangePrivacyText" = "Choose who exactly can see which of your info."; + +"DeleteAccount.Options.SetTwoStepAuthTitle" = "Enable Two-Step Verification"; +"DeleteAccount.Options.SetTwoStepAuthText" = "Set a password that will be required each time you log in."; + +"DeleteAccount.Options.SetPasscodeTitle" = "Set a Passcode"; +"DeleteAccount.Options.SetPasscodeText" = "Lock the app with a passcode so that others can't open it."; + +"DeleteAccount.Options.ClearCacheTitle" = "Clear Cache"; +"DeleteAccount.Options.ClearCacheText" = "Free up disk space on your device; your media will stay in the cloud."; + +"DeleteAccount.Options.ClearSyncedContactsTitle" = "Clear Synced Contacts"; +"DeleteAccount.Options.ClearSyncedContactsText" = "Remove any unnecessary contacts you may have synced."; + +"DeleteAccount.Options.DeleteChatsTitle" = "Quickly Delete Your Chats"; +"DeleteAccount.Options.DeleteChatsText" = "Learn how to remove any info you don’t need in a few taps."; + +"DeleteAccount.Options.ContactSupportTitle" = "Contact Support"; +"DeleteAccount.Options.ContactSupportText" = "Tell us about any issues; deleting account doesn't usually help."; + +"DeleteAccount.DeleteMyAccountTitle" = "Delete My Account"; +"DeleteAccount.DeleteMyAccount" = "Delete My Account"; + +"DeleteAccount.ComeBackLater" = "Come Back Later"; +"DeleteAccount.Continue" = "Continue"; + +"DeleteAccount.CloudStorageTitle" = "Your Free Cloud Storage"; +"DeleteAccount.CloudStorageText" = "You will lose access to all your Saved Messages as well as all messages, media and files from your chats."; + +"DeleteAccount.GroupsAndChannelsTitle" = "Your Groups and Channels"; +"DeleteAccount.GroupsAndChannelsText" = "The groups and channels you created will either get new admins or become orphaned."; +"DeleteAccount.GroupsAndChannelsInfo" = "You can transfer group and channel ownership to other users via Chat Info > Edit > Admins. [More info]()"; + +"DeleteAccount.MessageHistoryTitle" = "Your Message History"; +"DeleteAccount.MessageHistoryText" = "Your chat partners will keep their message history with you, including the messages you shared in secret chats.\n\nYou can remove any messages for both sides at any time, but this will not be possible if you delete your account. [More info]()"; + +"DeleteAccount.ConfirmationAlertTitle" = "Proceed to Delete Your Account?"; +"DeleteAccount.ConfirmationAlertText" = "Deleting your account will permanently delete your data!\n\nIt is imposible to reverse this action!"; +"DeleteAccount.ConfirmationAlertDelete" = "Delete My Account"; + +"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"; diff --git a/submodules/AccountUtils/Sources/AccountUtils.swift b/submodules/AccountUtils/Sources/AccountUtils.swift index 76d533e0f0..44d09f560f 100644 --- a/submodules/AccountUtils/Sources/AccountUtils.swift +++ b/submodules/AccountUtils/Sources/AccountUtils.swift @@ -5,6 +5,7 @@ import TelegramUIPreferences import AccountContext public let maximumNumberOfAccounts = 3 +public let maximumPremiumNumberOfAccounts = 4 public func activeAccountsAndPeers(context: AccountContext, includePrimary: Bool = false) -> Signal<((AccountContext, EnginePeer)?, [(AccountContext, EnginePeer, Int32)]), NoError> { let sharedContext = context.sharedContext 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/CheckNode/Sources/CheckNode.swift b/submodules/CheckNode/Sources/CheckNode.swift index edc567d3f8..227c77c35b 100644 --- a/submodules/CheckNode/Sources/CheckNode.swift +++ b/submodules/CheckNode/Sources/CheckNode.swift @@ -312,6 +312,15 @@ public class CheckLayer: CALayer { } } + public override init() { + self.theme = CheckNodeTheme(backgroundColor: .white, strokeColor: .blue, borderColor: .white, overlayBorder: false, hasInset: false, hasShadow: false) + self.content = .check + + super.init() + + self.isOpaque = false + } + public init(theme: CheckNodeTheme, content: CheckNodeContent = .check) { self.theme = theme self.content = content 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/InAppPurchaseManager/Sources/InAppPurchaseManager.swift b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift index 91eb0e8231..21f7dc3d6c 100644 --- a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift +++ b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift @@ -5,20 +5,68 @@ import StoreKit import Postbox import TelegramCore +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 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 { @@ -58,7 +106,6 @@ public final class InAppPurchaseManager: NSObject { } private let engine: TelegramEngine - private let premiumProductId: String private var products: [Product] = [] private var productsPromise = Promise<[Product]>([]) @@ -71,9 +118,8 @@ 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() @@ -90,11 +136,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() diff --git a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift index 715e5fa65b..6c7a0d04db 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift @@ -15,14 +15,16 @@ import TextFormat public class InviteLinkHeaderItem: ListViewItem, ItemListItem { public let context: AccountContext public let theme: PresentationTheme + public let title: String? public let text: String public let animationName: String public let sectionId: ItemListSectionId public let linkAction: ((ItemListTextItemLinkAction) -> Void)? - public init(context: AccountContext, theme: PresentationTheme, text: String, animationName: String, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) { + public init(context: AccountContext, theme: PresentationTheme, title: String? = nil, text: String, animationName: String, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) { self.context = context self.theme = theme + self.title = title self.text = text self.animationName = animationName self.sectionId = sectionId @@ -66,10 +68,12 @@ public class InviteLinkHeaderItem: ListViewItem, ItemListItem { } } -private let titleFont = Font.regular(13.0) +private let titleFont = Font.semibold(17.0) +private let textFont = Font.regular(14.0) class InviteLinkHeaderItemNode: ListViewItemNode { private let titleNode: TextNode + private let textNode: TextNode private var animationNode: AnimatedStickerNode private var item: InviteLinkHeaderItem? @@ -80,11 +84,17 @@ class InviteLinkHeaderItemNode: ListViewItemNode { self.titleNode.contentMode = .left self.titleNode.contentsScale = UIScreen.main.scale + self.textNode = TextNode() + self.textNode.isUserInteractionEnabled = false + self.textNode.contentMode = .left + self.textNode.contentsScale = UIScreen.main.scale + self.animationNode = DefaultAnimatedStickerNodeImpl() super.init(layerBacked: false, dynamicBounce: false) self.addSubnode(self.titleNode) + self.addSubnode(self.textNode) self.addSubnode(self.animationNode) } @@ -100,18 +110,27 @@ class InviteLinkHeaderItemNode: ListViewItemNode { func asyncLayout() -> (_ item: InviteLinkHeaderItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { let makeTitleLayout = TextNode.asyncLayout(self.titleNode) + let makeTextLayout = TextNode.asyncLayout(self.textNode) return { item, params, neighbors in - let leftInset: CGFloat = 32.0 + params.leftInset + let leftInset: CGFloat = 28.0 + params.leftInset let topInset: CGFloat = 124.0 + let spacing: CGFloat = 5.0 - let attributedText = parseMarkdownIntoAttributedString(item.text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.freeTextColor), link: MarkdownAttributeSet(font: titleFont, textColor: item.theme.list.itemAccentColor), linkAttribute: { contents in + let attributedTitle = NSAttributedString(string: item.title ?? "", font: titleFont, textColor: item.theme.list.itemPrimaryTextColor, paragraphAlignment: .center) + + let attributedText = parseMarkdownIntoAttributedString(item.text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: item.theme.list.freeTextColor), bold: MarkdownAttributeSet(font: textFont, textColor: item.theme.list.freeTextColor), link: MarkdownAttributeSet(font: textFont, textColor: item.theme.list.itemAccentColor), linkAttribute: { contents in return (TelegramTextAttributes.URL, contents) })) - - let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) - let contentSize = CGSize(width: params.width, height: topInset + titleLayout.size.height) + let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedTitle, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + + let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + + var contentSize = CGSize(width: params.width, height: topInset + textLayout.size.height) + if let _ = item.title { + contentSize.height += titleLayout.size.height + spacing + } let insets = itemListNeighborsGroupedInsets(neighbors, params) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) @@ -129,8 +148,16 @@ class InviteLinkHeaderItemNode: ListViewItemNode { strongSelf.animationNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: -10.0), size: iconSize) strongSelf.animationNode.updateLayout(size: iconSize) + var origin: CGFloat = topInset + 8.0 + let _ = titleApply() - strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleLayout.size.width) / 2.0), y: topInset + 8.0), size: titleLayout.size) + strongSelf.titleNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - titleLayout.size.width) / 2.0), y: origin), size: titleLayout.size) + if titleLayout.size.height > 0.0 { + origin += titleLayout.size.height + spacing + } + + let _ = textApply() + strongSelf.textNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - textLayout.size.width) / 2.0), y: origin), size: textLayout.size) } }) } @@ -150,9 +177,9 @@ class InviteLinkHeaderItemNode: ListViewItemNode { if let (gesture, location) = recognizer.lastRecognizedGestureAndLocation { switch gesture { case .tap: - let titleFrame = self.titleNode.frame - if let item = self.item, titleFrame.contains(location) { - if let (_, attributes) = self.titleNode.attributesAtPoint(CGPoint(x: location.x - titleFrame.minX, y: location.y - titleFrame.minY)) { + let textFrame = self.textNode.frame + if let item = self.item, textFrame.contains(location) { + if let (_, attributes) = self.textNode.attributesAtPoint(CGPoint(x: location.x - textFrame.minX, y: location.y - textFrame.minY)) { if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { item.linkAction?(.tap(url)) } diff --git a/submodules/PeerInfoUI/Sources/IncreaseLimitFooterItem.swift b/submodules/PeerInfoUI/Sources/IncreaseLimitFooterItem.swift index 6ec922464f..befb39d4f9 100644 --- a/submodules/PeerInfoUI/Sources/IncreaseLimitFooterItem.swift +++ b/submodules/PeerInfoUI/Sources/IncreaseLimitFooterItem.swift @@ -23,7 +23,7 @@ final class IncreaseLimitFooterItem: ItemListControllerFooterItem { func isEqual(to: ItemListControllerFooterItem) -> Bool { if let item = to as? IncreaseLimitFooterItem { - return self.theme === item.theme && self.title == item.title + return self.theme === item.theme && self.title == item.title && self.colorful == item.colorful } else { return false } 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/gift.scn b/submodules/PremiumUI/Resources/gift.scn new file mode 100644 index 0000000000000000000000000000000000000000..14f72e0681d5a22da7076ada94ca112c19c5b84f GIT binary patch literal 30009 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 B#l!#r literal 0 HcmV?d00001 diff --git a/submodules/PremiumUI/Sources/DataRainView.swift b/submodules/PremiumUI/Sources/DataRainView.swift index 122971f7d7..c3b95828b6 100644 --- a/submodules/PremiumUI/Sources/DataRainView.swift +++ b/submodules/PremiumUI/Sources/DataRainView.swift @@ -14,10 +14,6 @@ public final class MatrixView: MTKView, MTKViewDelegate, PhoneDemoDecorationView private var displayLink: CADisplayLink? -// private var metalLayer: CAMetalLayer { -// return self.layer as! CAMetalLayer -// } - private let symbolTexture: MTLTexture private let randomTexture: MTLTexture diff --git a/submodules/PremiumUI/Sources/GiftAvatarComponent.swift b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift new file mode 100644 index 0000000000..9069fab68b --- /dev/null +++ b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift @@ -0,0 +1,294 @@ +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.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) + self.avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: component.peer, size: avatarSize, font: avatarPlaceholderFont(size: 78.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/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift new file mode 100644 index 0000000000..903c29b49e --- /dev/null +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -0,0 +1,1286 @@ +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 = nil + }) + } + } + + 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 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 + ) + + let 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 + ) + + 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(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)) + ) + + context.add(subtitle + .position(CGPoint(x: insets.left + 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) + context.add(label + .position(CGPoint(x: context.availableSize.width - insets.right - label.size.width / 2.0, y: size.height / 2.0)) + ) + + 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: [InAppPurchaseManager.Product] + let selectedProductId: String + + let present: (ViewController) -> Void + let selectProduct: (String) -> Void + + init(context: AccountContext, peer: EnginePeer, products: [InAppPurchaseManager.Product], 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) + let termsText = Child(MultilineTextComponent.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 arrowColor = theme.list.disclosureArrowColor + + 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 + for product in component.products { + let monthsCount: Int + let giftTitle: String + let discount: String + switch product.id { + case "org.telegram.telegramPremium.twelveMonths": + giftTitle = strings.Premium_Gift_Years(1) + monthsCount = 12 + discount = "-15%" + case "org.telegram.telegramPremium.sixMonths": + giftTitle = strings.Premium_Gift_Months(6) + monthsCount = 6 + discount = "-10%" + case "org.telegram.telegramPremium.threeMonths": + giftTitle = strings.Premium_Gift_Months(3) + monthsCount = 3 + discount = "-7%" + default: + giftTitle = "" + monthsCount = 1 + discount = "" + } + + items.append(ProductGroupComponent.Item( + AnyComponentWithIdentity( + id: product.id, + component: AnyComponent( + GiftComponent( + title: giftTitle, + totalPrice: product.price, + perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth(monthsCount)).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 + + let textSideInset: CGFloat = 16.0 + + 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: strings.Premium_Gift_Info, + attributes: termsMarkdownAttributes + ) + + let accountContext = component.context + let peerId = component.peer.id + let present = component.present + + 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: .profile(peerId)) + 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: size.height + termsText.size.height / 2.0)) +// ) + context.add(termsText + .position(CGPoint(x: sideInset + environment.safeInsets.left + textSideInset + termsText.size.width / 2.0, y: size.height + 164.0 + termsText.size.height / 2.0)) + ) + size.height += termsText.size.height + size.height += 10.0 + size.height += scrollEnvironment.insets.bottom + + return size + } + } +} + +private final class PremiumGiftScreenComponent: CombinedComponent { + typealias EnvironmentType = ViewControllerComponentContainer.Environment + + let context: AccountContext + let peerId: PeerId + let updateInProgress: (Bool) -> Void + let present: (ViewController) -> Void + let push: (ViewController) -> Void + let completion: () -> Void + + init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping () -> Void) { + self.context = context + self.peerId = peerId + 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 + } + return true + } + + final class State: ComponentState { + private let context: AccountContext + private let peerId: PeerId + private let updateInProgress: (Bool) -> Void + private let present: (ViewController) -> Void + private let completion: () -> Void + + var topContentOffset: CGFloat? + var bottomContentOffset: CGFloat? + + var hasIdleAnimations = true + + var inProgress = false + + var peer: EnginePeer? + var products: [InAppPurchaseManager.Product]? + var selectedProductId: String? + + private var disposable: Disposable? + private var paymentDisposable = MetaDisposable() + private var activationDisposable = MetaDisposable() + + init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping () -> Void) { + self.context = context + self.peerId = peerId + 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 { + strongSelf.products = products.filter { !$0.isSubscription }.sorted(by: { $0.priceValue.compare($1.priceValue) == .orderedDescending }) + 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 + } + +// 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() + |> deliverOnMainQueue).start(next: { [weak self] available in + if let strongSelf = self { + if available { + strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(product) + |> 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) + strongSelf.completion() + + 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 { + let _ = updatePremiumPromoConfigurationOnce(account: strongSelf.context.account).start() + strongSelf.inProgress = false + strongSelf.updateInProgress(false) + + strongSelf.updated(transition: .easeInOut(duration: 0.25)) + strongSelf.completion() + } + })) + } + }, 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, 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) + + 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)) + ) + + if let peer = state.peer, let products = state.products, let selectedProductId = state.selectedProductId { + let scrollContent = scrollContent.update( + component: ScrollComponent( + content: AnyComponent(PremiumGiftScreenContentComponent( + context: context.component.context, + peer: peer, + products: products, + selectedProductId: 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 + } + + if let peer = context.state.peer { + let star = star.update( + component: GiftAvatarComponent( + context: context.component.context, + peer: 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() + }) + }) + ) + + 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) { + self.context = context + + var updateInProgressImpl: ((Bool) -> Void)? + var pushImpl: ((ViewController) -> Void)? +// var presentImpl: ((ViewController) -> Void)? + var completionImpl: (() -> Void)? + super.init(context: context, component: PremiumGiftScreenComponent( + context: context, + peerId: peerId, + updateInProgress: { inProgress in + updateInProgressImpl?(inProgress) + }, + present: { c in + pushImpl?(c) + }, + push: { c in + pushImpl?(c) + }, + completion: { + completionImpl?() + } + ), 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 + } + } + +// presentImpl = { [weak self] c in +// self?.present(c, in: .window(.root)) +// } + + pushImpl = { [weak self] c in + self?.push(c) + } + + completionImpl = { [weak self] in + if let strongSelf = self { + strongSelf.view.addSubview(ConfettiView(frame: strongSelf.view.bounds)) + } + } + } + + 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..c62048a366 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 @@ -470,135 +469,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] @@ -1379,7 +1249,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) diff --git a/submodules/PremiumUI/Sources/PremiumStarComponent.swift b/submodules/PremiumUI/Sources/PremiumStarComponent.swift index 9ec5fe42b9..ce5558ca11 100644 --- a/submodules/PremiumUI/Sources/PremiumStarComponent.swift +++ b/submodules/PremiumUI/Sources/PremiumStarComponent.swift @@ -410,7 +410,7 @@ class PremiumStarComponent: Component { 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.35, 0.3) + particleSystem.particleColorVariation = SCNVector4(0.15, 0.2, 0.15, 0.3) particleSystem.speedFactor = 2.0 particleSystem.particleVelocity = 2.2 particleSystem.birthRate = 4.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/SettingsUI/BUILD b/submodules/SettingsUI/BUILD index 8dd9f3c616..3e2c5fb18d 100644 --- a/submodules/SettingsUI/BUILD +++ b/submodules/SettingsUI/BUILD @@ -101,6 +101,7 @@ swift_library( "//submodules/ListMessageItem:ListMessageItem", "//submodules/PaymentMethodUI:PaymentMethodUI", "//submodules/PremiumUI:PremiumUI", + "//submodules/InviteLinksUI:InviteLinksUI", ], visibility = [ "//visibility:public", diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift new file mode 100644 index 0000000000..9c1886c473 --- /dev/null +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -0,0 +1,190 @@ +import Foundation +import UIKit +import Display +import SwiftSignalKit +import Postbox +import TelegramCore +import LegacyComponents +import TelegramPresentationData +import ItemListUI +import PresentationDataUtils +import AccountContext +import AlertUI +import PresentationDataUtils +import UrlHandling +import InviteLinksUI + +private struct DeleteAccountDataArguments { + let context: AccountContext + let openLink: (String) -> Void +} + +private enum DeleteAccountDataSection: Int32 { + case main +} + +private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { + case header(PresentationTheme, String, String, String) + + case peers(PresentationTheme, [Peer]) + case info(PresentationTheme, String) + + var section: ItemListSectionId { + switch self { + case .header, .peers, .info: + return DeleteAccountDataSection.main.rawValue + } + } + + var stableId: Int32 { + switch self { + case .header: + return 0 + case .peers: + return 1 + case .info: + return 3 + } + } + + static func == (lhs: DeleteAccountDataEntry, rhs: DeleteAccountDataEntry) -> Bool { + switch lhs { + case let .header(lhsTheme, lhsAnimation, lhsTitle, lhsText): + if case let .header(rhsTheme, rhsAnimation, rhsTitle, rhsText) = rhs, lhsTheme === rhsTheme, lhsAnimation == rhsAnimation, lhsTitle == rhsTitle, lhsText == rhsText { + return true + } else { + return false + } + case let .peers(lhsTheme, lhsPeers): + if case let .peers(rhsTheme, rhsPeers) = rhs, lhsTheme === rhsTheme, arePeerArraysEqual(lhsPeers, rhsPeers) { + return true + } else { + return false + } + case let .info(lhsTheme, lhsText): + if case let .info(rhsTheme, rhsText) = rhs, lhsTheme === rhsTheme, lhsText == rhsText { + return true + } else { + return false + } + } + } + + static func <(lhs: DeleteAccountDataEntry, rhs: DeleteAccountDataEntry) -> Bool { + return lhs.stableId < rhs.stableId + } + + func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { + let arguments = arguments as! DeleteAccountDataArguments + switch self { + case let .header(theme, animation, title, text): + return InviteLinkHeaderItem(context: arguments.context, theme: theme, title: title, text: text, animationName: animation, sectionId: self.section, linkAction: nil) + case let .peers(_, peers): + return ItemListTextItem(presentationData: presentationData, text: .plain(peers.first?.debugDisplayTitle ?? ""), sectionId: self.section) + case let .info(_, text): + return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section) + } + } +} + +private func deleteAccountDataEntries(presentationData: PresentationData, mode: DeleteAccountDataMode, peers: [Peer]) -> [DeleteAccountDataEntry] { + var entries: [DeleteAccountDataEntry] = [] + + let headerTitle: String + let headerText: String + let headerAnimation: String + + switch mode { + case .peers: + headerAnimation = "" + headerTitle = presentationData.strings.DeleteAccount_CloudStorageTitle + headerText = presentationData.strings.DeleteAccount_CloudStorageText + case .groups: + headerAnimation = "" + headerTitle = presentationData.strings.DeleteAccount_GroupsAndChannelsTitle + headerText = presentationData.strings.DeleteAccount_GroupsAndChannelsText + case .messages: + headerAnimation = "" + headerTitle = presentationData.strings.DeleteAccount_MessageHistoryTitle + headerText = presentationData.strings.DeleteAccount_MessageHistoryText + } + + entries.append(.header(presentationData.theme, headerAnimation, headerTitle, headerText)) + entries.append(.peers(presentationData.theme, peers)) + + if case .groups = mode { + entries.append(.info(presentationData.theme, presentationData.strings.DeleteAccount_GroupsAndChannelsInfo)) + } + + return entries +} + +enum DeleteAccountDataMode { + case peers + case groups + case messages +} + +func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDataMode) -> ViewController { + var replaceTopControllerImpl: ((ViewController) -> Void)? + var dismissImpl: (() -> Void)? + + let arguments = DeleteAccountDataArguments(context: context, openLink: { _ in + + }) + + let peers: Signal<[Peer], NoError> = .single([]) + + let signal = combineLatest(queue: .mainQueue(), + context.sharedContext.presentationData, + peers + ) + |> map { presentationData, peers -> (ItemListControllerState, (ItemListNodeState, Any)) in + let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { + dismissImpl?() + }) + + let footerItem = DeleteAccountFooterItem(theme: presentationData.theme, title: presentationData.strings.DeleteAccount_ComeBackLater, secondaryTitle: presentationData.strings.DeleteAccount_Continue, action: { + dismissImpl?() + }, secondaryAction: { + let nextMode: DeleteAccountDataMode? + switch mode { + case .peers: + nextMode = .groups + case .groups: + nextMode = .messages + case .messages: + nextMode = nil + } + + if let nextMode = nextMode { + let controller = deleteAccountDataController(context: context, mode: nextMode) + replaceTopControllerImpl?(controller) + } + }) + + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.DeleteAccount_DeleteMyAccountTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: deleteAccountDataEntries(presentationData: presentationData, mode: mode, peers: peers), style: .blocks, footerItem: footerItem) + + return (controllerState, (listState, arguments)) + } + + let controller = ItemListController(context: context, state: signal, tabBarItem: nil) + replaceTopControllerImpl = { [weak controller] c in + if let navigationController = controller?.navigationController as? NavigationController { + navigationController.pushViewController(c, completion: { [weak navigationController, weak controller, weak c] in + if let navigationController = navigationController { + let controllers = navigationController.viewControllers.filter { $0 !== controller } + c?.navigationPresentation = .modal + navigationController.setViewControllers(controllers, animated: false) + } + }) + } + } + dismissImpl = { [weak controller] in + let _ = controller?.dismiss() + } + + return controller +} + diff --git a/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift b/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift new file mode 100644 index 0000000000..208bd12c34 --- /dev/null +++ b/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift @@ -0,0 +1,152 @@ +import Foundation +import UIKit +import AsyncDisplayKit +import Display +import TelegramPresentationData +import ItemListUI +import PresentationDataUtils +import SolidRoundedButtonNode +import AppBundle + +final class DeleteAccountFooterItem: ItemListControllerFooterItem { + let theme: PresentationTheme + let title: String + let secondaryTitle: String + let action: () -> Void + let secondaryAction: () -> Void + + init(theme: PresentationTheme, title: String, secondaryTitle: String, action: @escaping () -> Void, secondaryAction: @escaping () -> Void) { + self.theme = theme + self.title = title + self.secondaryTitle = secondaryTitle + self.action = action + self.secondaryAction = secondaryAction + } + + func isEqual(to: ItemListControllerFooterItem) -> Bool { + if let item = to as? DeleteAccountFooterItem { + return self.theme === item.theme && self.title == item.title && self.secondaryTitle == item.secondaryTitle + } else { + return false + } + } + + func node(current: ItemListControllerFooterItemNode?) -> ItemListControllerFooterItemNode { + if let current = current as? DeleteAccountFooterItemNode { + current.item = self + return current + } else { + return DeleteAccountFooterItemNode(item: self) + } + } +} + +final class DeleteAccountFooterItemNode: ItemListControllerFooterItemNode { + private let backgroundNode: NavigationBackgroundNode + private let separatorNode: ASDisplayNode + private let buttonNode: SolidRoundedButtonNode + private let secondaryButtonNode: HighlightTrackingButtonNode + + private var validLayout: ContainerViewLayout? + + var item: DeleteAccountFooterItem { + didSet { + self.updateItem() + if let layout = self.validLayout { + let _ = self.updateLayout(layout: layout, transition: .immediate) + } + } + } + + init(item: DeleteAccountFooterItem) { + self.item = item + + self.backgroundNode = NavigationBackgroundNode(color: item.theme.rootController.tabBar.backgroundColor) + self.separatorNode = ASDisplayNode() + + self.buttonNode = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(backgroundColor: .black, foregroundColor: .white), height: 50.0, cornerRadius: 11.0, gloss: true) + + self.secondaryButtonNode = HighlightTrackingButtonNode() + + super.init() + + self.addSubnode(self.backgroundNode) + self.addSubnode(self.separatorNode) + self.addSubnode(self.buttonNode) + self.addSubnode(self.secondaryButtonNode) + + self.secondaryButtonNode.addTarget(self, action: #selector(self.secondaryButtonPressed), forControlEvents: .touchUpInside) + + self.updateItem() + } + + @objc private func secondaryButtonPressed() { + self.item.secondaryAction() + } + + private func updateItem() { + self.backgroundNode.updateColor(color: self.item.theme.rootController.tabBar.backgroundColor, transition: .immediate) + self.separatorNode.backgroundColor = self.item.theme.rootController.tabBar.separatorColor + + let backgroundColor = self.item.theme.list.itemCheckColors.fillColor + let textColor = self.item.theme.list.itemCheckColors.foregroundColor + + self.buttonNode.updateTheme(SolidRoundedButtonTheme(backgroundColor: backgroundColor, foregroundColor: textColor), animated: false) + self.buttonNode.title = self.item.title + + self.buttonNode.pressed = { [weak self] in + self?.item.action() + } + + self.secondaryButtonNode.setTitle(self.item.secondaryTitle, with: Font.regular(17.0), with: self.item.theme.list.itemAccentColor, for: .normal) + } + + override func updateBackgroundAlpha(_ alpha: CGFloat, transition: ContainedViewLayoutTransition) { + transition.updateAlpha(node: self.backgroundNode, alpha: alpha) + transition.updateAlpha(node: self.separatorNode, alpha: alpha) + } + + override func updateLayout(layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) -> CGFloat { + self.validLayout = layout + + let buttonInset: CGFloat = 16.0 + let buttonWidth = layout.size.width - layout.safeInsets.left - layout.safeInsets.right - buttonInset * 2.0 + let buttonHeight = self.buttonNode.updateLayout(width: buttonWidth, transition: transition) + let topInset: CGFloat = 9.0 + let bottomInset: CGFloat = 23.0 + let spacing: CGFloat = 23.0 + + let insets = layout.insets(options: [.input]) + + let secondaryButtonSize = self.secondaryButtonNode.measure(CGSize(width: buttonWidth, height: CGFloat.greatestFiniteMagnitude)) + + var panelHeight: CGFloat = buttonHeight + topInset + spacing + secondaryButtonSize.height + bottomInset + let totalPanelHeight: CGFloat + if let inputHeight = layout.inputHeight, inputHeight > 0.0 { + totalPanelHeight = panelHeight + insets.bottom + } else { + panelHeight += insets.bottom + totalPanelHeight = panelHeight + } + + let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - totalPanelHeight), size: CGSize(width: layout.size.width, height: panelHeight)) + transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + buttonInset, y: panelFrame.minY + topInset), size: CGSize(width: buttonWidth, height: buttonHeight))) + + transition.updateFrame(node: self.secondaryButtonNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - secondaryButtonSize.width) / 2.0), y: panelFrame.minY + topInset + buttonHeight + spacing), size: secondaryButtonSize)) + + transition.updateFrame(node: self.backgroundNode, frame: panelFrame) + self.backgroundNode.update(size: panelFrame.size, transition: transition) + + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: panelFrame.origin, size: CGSize(width: panelFrame.width, height: UIScreenPixel))) + + return panelHeight + } + + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { + if self.backgroundNode.frame.contains(point) { + return true + } else { + return false + } + } +} diff --git a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift new file mode 100644 index 0000000000..7325104044 --- /dev/null +++ b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift @@ -0,0 +1,349 @@ +import Foundation +import UIKit +import Display +import SwiftSignalKit +import Postbox +import TelegramCore +import LegacyComponents +import TelegramPresentationData +import ItemListUI +import PresentationDataUtils +import OverlayStatusController +import AccountContext +import AlertUI +import PresentationDataUtils +import UrlHandling +import AccountUtils +import PremiumUI + +private struct DeleteAccountOptionsArguments { + let changePhoneNumber: () -> Void + let addAccount: () -> Void + let setupPrivacy: () -> Void + let setTwoStepAuth: () -> Void + let setPasscode: () -> Void + let clearCache: () -> Void + let contactSupport: () -> Void + let deleteAccount: () -> Void +} + +private enum DeleteAccountOptionsSection: Int32 { + case add + case privacy + case remove + case support + case delete +} + +private enum DeleteAccountOptionsEntry: ItemListNodeEntry, Equatable { + case changePhoneNumber(PresentationTheme, String, String) + case addAccount(PresentationTheme, String, String) + + case changePrivacy(PresentationTheme, String, String) + case setTwoStepAuth(PresentationTheme, String, String) + case setPasscode(PresentationTheme, String, String) + + case clearCache(PresentationTheme, String, String) + case clearSyncedContacts(PresentationTheme, String, String) + case deleteChats(PresentationTheme, String, String) + + case contactSupport(PresentationTheme, String, String) + + case deleteAccount(PresentationTheme, String) + + var section: ItemListSectionId { + switch self { + case .changePhoneNumber, .addAccount: + return DeleteAccountOptionsSection.add.rawValue + case .changePrivacy, .setTwoStepAuth, .setPasscode: + return DeleteAccountOptionsSection.privacy.rawValue + case .clearCache, .clearSyncedContacts, .deleteChats: + return DeleteAccountOptionsSection.remove.rawValue + case .contactSupport: + return DeleteAccountOptionsSection.support.rawValue + case .deleteAccount: + return DeleteAccountOptionsSection.delete.rawValue + } + } + + var stableId: Int32 { + switch self { + case .changePhoneNumber: + return 0 + case .addAccount: + return 1 + case .changePrivacy: + return 2 + case .setTwoStepAuth: + return 3 + case .setPasscode: + return 4 + case .clearCache: + return 5 + case .clearSyncedContacts: + return 6 + case .deleteChats: + return 7 + case .contactSupport: + return 8 + case .deleteAccount: + return 9 + } + } + + static func <(lhs: DeleteAccountOptionsEntry, rhs: DeleteAccountOptionsEntry) -> Bool { + return lhs.stableId < rhs.stableId + } + + func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { + let arguments = arguments as! DeleteAccountOptionsArguments + switch self { + case let .changePhoneNumber(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.changePhoneNumber, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.changePhoneNumber() + }) + case let .addAccount(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.deleteAddAccount, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.addAccount() + }) + case let .changePrivacy(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.security, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.setupPrivacy() + }) + case let .setTwoStepAuth(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.setPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.setTwoStepAuth() + }) + case let .setPasscode(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.deleteSetPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.setPasscode() + }) + case let .clearCache(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.dataAndStorage, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.clearCache() + }) + case let .clearSyncedContacts(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.clearSynced, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.clearCache() + }) + case let .deleteChats(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.deleteChats, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.clearCache() + }) + case let .contactSupport(_, title, text): + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.support, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.contactSupport() + }) + case let .deleteAccount(_, title): + return ItemListActionItem(presentationData: presentationData, title: title, kind: .destructive, alignment: .natural, sectionId: self.section, style: .blocks, action: { + arguments.deleteAccount() + }) + } + } +} + +private func deleteAccountOptionsEntries(presentationData: PresentationData, canAddAccounts: Bool, hasTwoStepAuth: Bool, hasPasscode: Bool) -> [DeleteAccountOptionsEntry] { + var entries: [DeleteAccountOptionsEntry] = [] + + entries.append(.changePhoneNumber(presentationData.theme, presentationData.strings.DeleteAccount_Options_ChangePhoneNumberTitle, presentationData.strings.DeleteAccount_Options_ChangePhoneNumberText)) + if canAddAccounts { + entries.append(.addAccount(presentationData.theme, presentationData.strings.DeleteAccount_Options_AddAccountTitle, presentationData.strings.DeleteAccount_Options_AddAccountText)) + } + + entries.append(.changePrivacy(presentationData.theme, presentationData.strings.DeleteAccount_Options_ChangePrivacyTitle, presentationData.strings.DeleteAccount_Options_ChangePrivacyText)) + if !hasTwoStepAuth { + entries.append(.setTwoStepAuth(presentationData.theme, presentationData.strings.DeleteAccount_Options_SetTwoStepAuthTitle, presentationData.strings.DeleteAccount_Options_SetTwoStepAuthText)) + } + if !hasPasscode { + entries.append(.setPasscode(presentationData.theme, presentationData.strings.DeleteAccount_Options_SetPasscodeTitle, presentationData.strings.DeleteAccount_Options_SetPasscodeText)) + } + entries.append(.clearCache(presentationData.theme, presentationData.strings.DeleteAccount_Options_ClearCacheTitle, presentationData.strings.DeleteAccount_Options_ClearCacheText)) + entries.append(.clearSyncedContacts(presentationData.theme, presentationData.strings.DeleteAccount_Options_ClearSyncedContactsTitle, presentationData.strings.DeleteAccount_Options_ClearSyncedContactsText)) + entries.append(.deleteChats(presentationData.theme, presentationData.strings.DeleteAccount_Options_DeleteChatsTitle, presentationData.strings.DeleteAccount_Options_DeleteChatsText)) + + entries.append(.contactSupport(presentationData.theme, presentationData.strings.DeleteAccount_Options_ContactSupportTitle, presentationData.strings.DeleteAccount_Options_ContactSupportText)) + + entries.append(.deleteAccount(presentationData.theme, presentationData.strings.DeleteAccount_DeleteMyAccount)) + + return entries +} + +public func deleteAccountOptionsController(context: AccountContext, navigationController: NavigationController, hasTwoStepAuth: Bool) -> ViewController { + var pushControllerImpl: ((ViewController) -> Void)? + var presentControllerImpl: ((ViewController, Any?) -> Void)? + var replaceTopControllerImpl: ((ViewController, Bool) -> Void)? + var dismissImpl: (() -> Void)? + + let supportPeerDisposable = MetaDisposable() + + let arguments = DeleteAccountOptionsArguments(changePhoneNumber: { + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.engine.account.peerId)) + |> deliverOnMainQueue).start(next: { accountPeer in + guard let accountPeer = accountPeer, case let .user(user) = accountPeer else { + return + } + let introController = PrivacyIntroController(context: context, mode: .changePhoneNumber(user.phone ?? ""), proceedAction: { + replaceTopControllerImpl?(ChangePhoneNumberController(context: context), false) + }) + pushControllerImpl?(introController) + dismissImpl?() + }) + }, addAccount: { + let _ = (activeAccountsAndPeers(context: context) + |> take(1) + |> deliverOnMainQueue + ).start(next: { accountAndPeer, accountsAndPeers in + var maximumAvailableAccounts: Int = 3 + if accountAndPeer?.1.isPremium == true && !context.account.testingEnvironment { + maximumAvailableAccounts = 4 + } + var count: Int = 1 + for (accountContext, peer, _) in accountsAndPeers { + if !accountContext.account.testingEnvironment { + if peer.isPremium { + maximumAvailableAccounts = 4 + } + count += 1 + } + } + + if count >= maximumAvailableAccounts { + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumLimitScreen(context: context, subject: .accounts, count: Int32(count), action: { + let controller = PremiumIntroScreen(context: context, source: .accounts) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + pushControllerImpl?(controller) + } else { + context.sharedContext.beginNewAuth(testingEnvironment: context.account.testingEnvironment) + + dismissImpl?() + } + }) + }, setupPrivacy: { + + }, setTwoStepAuth: { + + }, setPasscode: { + let _ = passcodeOptionsAccessController(context: context, pushController: { controller in + replaceTopControllerImpl?(controller, false) + }, completion: { _ in + replaceTopControllerImpl?(passcodeOptionsController(context: context), false) + }).start(next: { controller in + if let controller = controller { + pushControllerImpl?(controller) + } + }) + dismissImpl?() + }, clearCache: { + pushControllerImpl?(storageUsageController(context: context)) + dismissImpl?() + }, contactSupport: { [weak navigationController] in + let supportPeer = Promise() + supportPeer.set(context.engine.peers.supportPeerId()) + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + var faqUrl = presentationData.strings.Settings_FAQ_URL + if faqUrl == "Settings.FAQ_URL" || faqUrl.isEmpty { + faqUrl = "https://telegram.org/faq#general" + } + let resolvedUrl = resolveInstantViewUrl(account: context.account, url: faqUrl) + + let resolvedUrlPromise = Promise() + resolvedUrlPromise.set(resolvedUrl) + + let openFaq: (Promise) -> Void = { resolvedUrl in + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) + presentControllerImpl?(controller, nil) + let _ = (resolvedUrl.get() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak controller] resolvedUrl in + controller?.dismiss() + dismissImpl?() + + context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peer, navigation in + }, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { controller, arguments in + pushControllerImpl?(controller) + }, dismissInput: {}, contentContext: nil) + }) + } + + presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Settings_FAQ_Intro, actions: [ + TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_FAQ_Button, action: { + openFaq(resolvedUrlPromise) + dismissImpl?() + }), + TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: { + supportPeerDisposable.set((supportPeer.get() + |> take(1) + |> deliverOnMainQueue).start(next: { peerId in + if let peerId = peerId, let navigationController = navigationController { + dismissImpl?() + context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(id: peerId))) + } + })) + }) + ]), nil) + }, deleteAccount: { + let controller = deleteAccountDataController(context: context, mode: .peers) + replaceTopControllerImpl?(controller, true) + }) + + let signal = combineLatest(queue: .mainQueue(), + context.sharedContext.presentationData, + context.sharedContext.accountManager.accessChallengeData(), + activeAccountsAndPeers(context: context) + ) + |> map { presentationData, accessChallengeData, accountsAndPeers -> (ItemListControllerState, (ItemListNodeState, Any)) in + let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { + dismissImpl?() + }) + + var hasPasscode = false + switch accessChallengeData.data { + case .numericalPassword, .plaintextPassword: + hasPasscode = true + default: + break + } + + let canAddAccounts = accountsAndPeers.1.count + 1 < maximumNumberOfAccounts + + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.DeleteAccount_AlternativeOptionsTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: deleteAccountOptionsEntries(presentationData: presentationData, canAddAccounts: canAddAccounts, hasTwoStepAuth: hasTwoStepAuth, hasPasscode: hasPasscode), style: .blocks) + + return (controllerState, (listState, arguments)) + } + + let controller = ItemListController(context: context, state: signal, tabBarItem: nil) + controller.navigationPresentation = .modal + pushControllerImpl = { [weak navigationController] value in + navigationController?.pushViewController(value, animated: false) + } + presentControllerImpl = { [weak controller] value, arguments in + controller?.present(value, in: .window(.root), with: arguments ?? ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) + } + replaceTopControllerImpl = { [weak navigationController] c, complex in + if complex { + navigationController?.pushViewController(c, completion: { [weak navigationController, weak controller, weak c] in + if let navigationController = navigationController { + let controllers = navigationController.viewControllers.filter { $0 !== controller } + c?.navigationPresentation = .modal + navigationController.setViewControllers(controllers, animated: false) + } + }) + } else { + navigationController?.replaceTopController(c, animated: true) + } + } + dismissImpl = { [weak controller] in + let _ = controller?.dismiss() + } + + return controller +} + diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift index 3b8b55c925..6731dbcd62 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift @@ -90,5 +90,10 @@ public struct PresentationResourcesSettings { public static let clearCache = renderIcon(name: "Settings/Menu/ClearCache") public static let changePhoneNumber = renderIcon(name: "Settings/Menu/ChangePhoneNumber") + public static let deleteAddAccount = renderIcon(name: "Settings/Menu/DeleteAddAccount") + public static let deleteSetPasscode = renderIcon(name: "Settings/Menu/FaceId") + public static let deleteChats = renderIcon(name: "Settings/Menu/DeleteChats") + public static let clearSynced = renderIcon(name: "Settings/Menu/ClearSynced") + public static let websites = renderIcon(name: "Settings/Menu/Websites") } diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/Contents.json new file mode 100644 index 0000000000..f933ba9c44 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "gift.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/gift.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/gift.pdf new file mode 100644 index 0000000000..407ead689d --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Context Menu/Gift.imageset/gift.pdf @@ -0,0 +1,512 @@ +%PDF-1.7 + +1 0 obj + << /Type /XObject + /Length 2 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 24.000000 24.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 7.992188 7.880981 cm +0.000000 0.000000 0.000000 scn +3.800998 1.276080 m +1.993796 0.168980 l +1.805881 0.053862 1.560225 0.112875 1.445107 0.300790 c +1.388883 0.392569 1.372121 0.503168 1.398624 0.607484 c +1.678378 1.708605 l +1.779364 2.106091 2.051364 2.438358 2.421074 2.615862 c +4.392641 3.562446 l +4.484557 3.606576 4.523294 3.716863 4.479164 3.808778 c +4.443426 3.883215 4.362605 3.924868 4.281243 3.910783 c +2.086636 3.530841 l +1.640524 3.453608 1.183040 3.576797 0.836031 3.867601 c +0.142737 4.448601 l +-0.026168 4.590147 -0.048346 4.841818 0.093201 5.010722 c +0.162044 5.092872 0.261042 5.143870 0.367897 5.152233 c +2.486118 5.318005 l +2.635765 5.329716 2.766179 5.424419 2.823627 5.563095 c +3.640796 7.535693 l +3.725137 7.739288 3.958555 7.835961 4.162150 7.751620 c +4.259909 7.711123 4.337579 7.633452 4.378077 7.535693 c +5.195247 5.563095 l +5.252695 5.424419 5.383109 5.329716 5.532755 5.318005 c +7.662615 5.151322 l +7.882316 5.134129 8.046480 4.942087 8.029286 4.722386 c +8.021015 4.616698 7.971026 4.518645 7.890352 4.449868 c +6.265997 3.065068 l +6.151649 2.967583 6.101762 2.814124 6.136929 2.668034 c +6.636304 0.593517 l +6.687879 0.379265 6.556002 0.163769 6.341750 0.112194 c +6.238800 0.087412 6.130221 0.104568 6.039927 0.159883 c +4.217875 1.276080 l +4.089963 1.354439 3.928910 1.354439 3.800998 1.276080 c +h +f* +n +Q + +endstream +endobj + +2 0 obj + 1398 +endobj + +3 0 obj + << /Type /XObject + /Length 4 0 R + /Group << /Type /Group + /S /Transparency + >> + /Subtype /Form + /Resources << >> + /BBox [ 0.000000 0.000000 24.000000 24.000000 ] + >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 6.000000 5.500000 cm +0.000000 0.000000 0.000000 scn +0.000000 6.000000 m +0.000000 9.313708 2.686292 12.000000 6.000000 12.000000 c +6.000000 12.000000 l +9.313708 12.000000 12.000000 9.313708 12.000000 6.000000 c +12.000000 6.000000 l +12.000000 2.686292 9.313708 0.000000 6.000000 0.000000 c +6.000000 0.000000 l +2.686292 0.000000 0.000000 2.686292 0.000000 6.000000 c +0.000000 6.000000 l +h +f +n +Q + +endstream +endobj + +4 0 obj + 459 +endobj + +5 0 obj + << /XObject << /X1 1 0 R >> + /ExtGState << /E1 << /SMask << /Type /Mask + /G 3 0 R + /S /Alpha + >> + /Type /ExtGState + >> >> + >> +endobj + +6 0 obj + << /Length 7 0 R >> +stream +/DeviceRGB CS +/DeviceRGB cs +q +1.000000 0.000000 -0.000000 1.000000 5.000000 2.669434 cm +0.000000 0.000000 0.000000 scn +0.665000 9.330566 m +0.665000 9.697836 0.367269 9.995566 0.000000 9.995566 c +-0.367269 9.995566 -0.665000 9.697836 -0.665000 9.330566 c +0.665000 9.330566 l +h +14.665000 9.330566 m +14.665000 9.697836 14.367270 9.995566 14.000000 9.995566 c +13.632730 9.995566 13.335000 9.697836 13.335000 9.330566 c +14.665000 9.330566 l +h +1.092019 1.548553 m +1.393923 2.141073 l +1.092019 1.548553 l +h +12.907981 1.548553 m +12.606077 2.141073 l +12.907981 1.548553 l +h +13.782013 2.422585 m +13.189494 2.724489 l +13.782013 2.422585 l +h +10.800000 1.995566 m +3.200000 1.995566 l +3.200000 0.665566 l +10.800000 0.665566 l +10.800000 1.995566 l +h +0.665000 4.530566 m +0.665000 9.330566 l +-0.665000 9.330566 l +-0.665000 4.530566 l +0.665000 4.530566 l +h +13.335000 9.330566 m +13.335000 4.530566 l +14.665000 4.530566 l +14.665000 9.330566 l +13.335000 9.330566 l +h +3.200000 1.995566 m +2.628974 1.995566 2.240699 1.996084 1.940556 2.020606 c +1.648176 2.044495 1.498463 2.087807 1.393923 2.141073 c +0.790115 0.956034 l +1.113398 0.791313 1.457623 0.725632 1.832252 0.695024 c +2.199117 0.665050 2.650920 0.665566 3.200000 0.665566 c +3.200000 1.995566 l +h +-0.665000 4.530566 m +-0.665000 3.981487 -0.665517 3.529683 -0.635543 3.162818 c +-0.604935 2.788190 -0.539253 2.443964 -0.374532 2.120682 c +0.810506 2.724489 l +0.757240 2.829030 0.713928 2.978743 0.690040 3.271122 c +0.665517 3.571266 0.665000 3.959541 0.665000 4.530566 c +-0.665000 4.530566 l +h +1.393923 2.141073 m +1.142726 2.269063 0.938497 2.473293 0.810506 2.724489 c +-0.374532 2.120682 l +-0.119030 1.619230 0.288663 1.211536 0.790115 0.956034 c +1.393923 2.141073 l +h +10.800000 0.665566 m +11.349079 0.665566 11.800883 0.665050 12.167748 0.695024 c +12.542377 0.725632 12.886601 0.791313 13.209885 0.956034 c +12.606077 2.141073 l +12.501536 2.087807 12.351824 2.044495 12.059443 2.020606 c +11.759300 1.996084 11.371026 1.995566 10.800000 1.995566 c +10.800000 0.665566 l +h +13.335000 4.530566 m +13.335000 3.959541 13.334483 3.571266 13.309960 3.271122 c +13.286072 2.978743 13.242760 2.829030 13.189494 2.724489 c +14.374533 2.120682 l +14.539253 2.443964 14.604935 2.788189 14.635543 3.162818 c +14.665517 3.529683 14.665000 3.981487 14.665000 4.530566 c +13.335000 4.530566 l +h +13.209885 0.956034 m +13.711337 1.211536 14.119030 1.619230 14.374533 2.120682 c +13.189494 2.724489 l +13.061502 2.473293 12.857274 2.269063 12.606077 2.141073 c +13.209885 0.956034 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 4.000000 11.169189 cm +0.000000 0.000000 0.000000 scn +2.000000 0.665811 m +2.367269 0.665811 2.665000 0.963541 2.665000 1.330811 c +2.665000 1.698080 2.367269 1.995811 2.000000 1.995811 c +2.000000 0.665811 l +h +14.000000 1.995811 m +13.632730 1.995811 13.335000 1.698080 13.335000 1.330811 c +13.335000 0.963541 13.632730 0.665811 14.000000 0.665811 c +14.000000 1.995811 l +h +0.115213 2.017745 m +0.716366 2.302069 l +0.115213 2.017745 l +h +0.686934 1.446023 m +0.402610 0.844871 l +0.686934 1.446023 l +h +15.884788 2.017745 m +16.485941 1.733420 l +15.884788 2.017745 l +h +15.313066 1.446023 m +15.597390 0.844871 l +15.313066 1.446023 l +h +14.855110 6.138789 m +15.139435 6.739942 l +14.855110 6.138789 l +h +15.807979 5.185921 m +15.206825 4.901597 l +15.807979 5.185921 l +h +3.125000 5.665811 m +12.875000 5.665811 l +12.875000 6.995811 l +3.125000 6.995811 l +3.125000 5.665811 l +h +1.875000 0.665811 m +2.000000 0.665811 l +2.000000 1.995811 l +1.875000 1.995811 l +1.875000 0.665811 l +h +14.125000 1.995811 m +14.000000 1.995811 l +14.000000 0.665811 l +14.125000 0.665811 l +14.125000 1.995811 l +h +-0.665000 3.205811 m +-0.665000 2.901255 -0.665455 2.635354 -0.648653 2.416179 c +-0.631310 2.189949 -0.592755 1.959262 -0.485940 1.733420 c +0.716366 2.302069 l +0.707968 2.319824 0.688916 2.368348 0.677456 2.517840 c +0.665455 2.674387 0.665000 2.880721 0.665000 3.205811 c +-0.665000 3.205811 l +h +1.875000 1.995811 m +1.549910 1.995811 1.343576 1.996265 1.187029 2.008266 c +1.037537 2.019727 0.989013 2.038779 0.971258 2.047176 c +0.402610 0.844871 l +0.628452 0.738055 0.859138 0.699501 1.085368 0.682158 c +1.304543 0.665356 1.570444 0.665811 1.875000 0.665811 c +1.875000 1.995811 l +h +-0.485940 1.733420 m +-0.301460 1.343369 0.012559 1.029351 0.402610 0.844871 c +0.971258 2.047176 l +0.859367 2.100097 0.769286 2.190177 0.716366 2.302069 c +-0.485940 1.733420 l +h +15.335000 3.205811 m +15.335000 2.880721 15.334545 2.674387 15.322544 2.517839 c +15.311084 2.368348 15.292032 2.319824 15.283634 2.302069 c +16.485941 1.733420 l +16.592754 1.959262 16.631310 2.189949 16.648653 2.416179 c +16.665455 2.635354 16.665001 2.901255 16.665001 3.205811 c +15.335000 3.205811 l +h +14.125000 0.665811 m +14.429556 0.665811 14.695457 0.665356 14.914632 0.682158 c +15.140862 0.699501 15.371549 0.738055 15.597390 0.844871 c +15.028742 2.047176 l +15.010986 2.038779 14.962463 2.019727 14.812971 2.008266 c +14.656424 1.996265 14.450090 1.995811 14.125000 1.995811 c +14.125000 0.665811 l +h +15.283634 2.302069 m +15.230714 2.190177 15.140634 2.100097 15.028742 2.047176 c +15.597390 0.844871 l +15.987441 1.029351 16.301460 1.343369 16.485941 1.733420 c +15.283634 2.302069 l +h +12.875000 5.665811 m +13.409972 5.665811 13.773717 5.665356 14.055506 5.643754 c +14.330238 5.622692 14.471831 5.584438 14.570786 5.537636 c +15.139435 6.739942 l +14.832394 6.885161 14.508637 6.942918 14.157166 6.969862 c +13.812751 6.996265 13.389438 6.995811 12.875000 6.995811 c +12.875000 5.665811 l +h +16.665001 3.205811 m +16.665001 3.720248 16.665455 4.143561 16.639051 4.487977 c +16.612108 4.839448 16.554352 5.163204 16.409132 5.470245 c +15.206825 4.901597 l +15.253628 4.802642 15.291882 4.661048 15.312943 4.386316 c +15.334545 4.104527 15.335000 3.740782 15.335000 3.205811 c +16.665001 3.205811 l +h +14.570786 5.537636 m +14.849992 5.405582 15.074771 5.180802 15.206825 4.901597 c +16.409132 5.470245 l +16.145517 6.027610 15.696799 6.476328 15.139435 6.739942 c +14.570786 5.537636 l +h +3.125000 6.995811 m +2.610562 6.995811 2.187250 6.996265 1.842834 6.969862 c +1.491363 6.942918 1.167606 6.885161 0.860566 6.739942 c +1.429214 5.537636 l +1.528168 5.584438 1.669762 5.622692 1.944495 5.643754 c +2.226283 5.665356 2.590028 5.665811 3.125000 5.665811 c +3.125000 6.995811 l +h +0.665000 3.205811 m +0.665000 3.740783 0.665455 4.104527 0.687057 4.386316 c +0.708118 4.661048 0.746372 4.802642 0.793174 4.901597 c +-0.409131 5.470245 l +-0.554351 5.163204 -0.612108 4.839448 -0.639052 4.487977 c +-0.665455 4.143561 -0.665000 3.720249 -0.665000 3.205811 c +0.665000 3.205811 l +h +0.860566 6.739942 m +0.303200 6.476328 -0.145517 6.027610 -0.409131 5.470245 c +0.793174 4.901597 l +0.925229 5.180802 1.150008 5.405582 1.429214 5.537636 c +0.860566 6.739942 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 8.000000 16.169922 cm +0.000000 0.000000 0.000000 scn +4.000000 1.330078 m +4.000000 0.665078 l +4.665000 0.665078 l +4.665000 1.330078 l +4.000000 1.330078 l +h +3.335000 3.330078 m +3.335000 1.330078 l +4.665000 1.330078 l +4.665000 3.330078 l +3.335000 3.330078 l +h +4.000000 1.995078 m +2.000000 1.995078 l +2.000000 0.665078 l +4.000000 0.665078 l +4.000000 1.995078 l +h +2.000000 1.995078 m +1.262700 1.995078 0.665000 2.592778 0.665000 3.330078 c +-0.665000 3.330078 l +-0.665000 1.858239 0.528161 0.665078 2.000000 0.665078 c +2.000000 1.995078 l +h +2.000000 4.665078 m +2.737300 4.665078 3.335000 4.067378 3.335000 3.330078 c +4.665000 3.330078 l +4.665000 4.801917 3.471839 5.995078 2.000000 5.995078 c +2.000000 4.665078 l +h +2.000000 5.995078 m +0.528161 5.995078 -0.665000 4.801917 -0.665000 3.330078 c +0.665000 3.330078 l +0.665000 4.067378 1.262700 4.665078 2.000000 4.665078 c +2.000000 5.995078 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 12.000000 16.169922 cm +0.000000 0.000000 0.000000 scn +0.000000 1.330078 m +-0.665000 1.330078 l +-0.665000 0.665078 l +0.000000 0.665078 l +0.000000 1.330078 l +h +2.000000 1.995078 m +0.000000 1.995078 l +0.000000 0.665078 l +2.000000 0.665078 l +2.000000 1.995078 l +h +0.665000 1.330078 m +0.665000 3.330078 l +-0.665000 3.330078 l +-0.665000 1.330078 l +0.665000 1.330078 l +h +3.335000 3.330078 m +3.335000 2.592778 2.737300 1.995078 2.000000 1.995078 c +2.000000 0.665078 l +3.471839 0.665078 4.665000 1.858239 4.665000 3.330078 c +3.335000 3.330078 l +h +2.000000 4.665078 m +2.737300 4.665078 3.335000 4.067378 3.335000 3.330078 c +4.665000 3.330078 l +4.665000 4.801917 3.471839 5.995078 2.000000 5.995078 c +2.000000 4.665078 l +h +2.000000 5.995078 m +0.528161 5.995078 -0.665000 4.801917 -0.665000 3.330078 c +0.665000 3.330078 l +0.665000 4.067378 1.262700 4.665078 2.000000 4.665078 c +2.000000 5.995078 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 12.000000 3.169922 cm +0.000000 0.000000 0.000000 scn +0.665000 3.330078 m +0.665000 3.697347 0.367269 3.995078 0.000000 3.995078 c +-0.367269 3.995078 -0.665000 3.697347 -0.665000 3.330078 c +0.665000 3.330078 l +h +-0.665000 1.330078 m +-0.665000 0.962809 -0.367269 0.665078 0.000000 0.665078 c +0.367269 0.665078 0.665000 0.962809 0.665000 1.330078 c +-0.665000 1.330078 l +h +-0.665000 3.330078 m +-0.665000 1.330078 l +0.665000 1.330078 l +0.665000 3.330078 l +-0.665000 3.330078 l +h +f +n +Q +q +/E1 gs +/X1 Do +Q + +endstream +endobj + +7 0 obj + 9085 +endobj + +8 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 24.000000 24.000000 ] + /Resources 5 0 R + /Contents 6 0 R + /Parent 9 0 R + >> +endobj + +9 0 obj + << /Kids [ 8 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +10 0 obj + << /Pages 9 0 R + /Type /Catalog + >> +endobj + +xref +0 11 +0000000000 65535 f +0000000010 00000 n +0000001656 00000 n +0000001679 00000 n +0000002386 00000 n +0000002408 00000 n +0000002706 00000 n +0000011847 00000 n +0000011870 00000 n +0000012043 00000 n +0000012117 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 10 0 R + /Size 11 +>> +startxref +12177 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/Contents.json new file mode 100644 index 0000000000..210f015b9f --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "clearsynced.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/clearsynced.pdf b/submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/clearsynced.pdf new file mode 100644 index 0000000000..80e9499bc2 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/ClearSynced.imageset/clearsynced.pdf @@ -0,0 +1,136 @@ +%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 0.000000 0.000000 cm +1.000000 0.584314 0.000000 scn +0.000000 18.799999 m +0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c +1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c +5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c +18.799999 30.000000 l +22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c +27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c +30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c +30.000000 11.200001 l +30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c +28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c +24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c +11.200000 0.000000 l +7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c +2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c +0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c +0.000000 18.799999 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 2.652100 8.000000 cm +1.000000 1.000000 1.000000 scn +15.347914 11.500000 m +15.347914 9.843145 14.004768 8.500000 12.347914 8.500000 c +10.691060 8.500000 9.347914 9.843145 9.347914 11.500000 c +9.347914 13.156855 10.691060 14.500000 12.347914 14.500000 c +14.004768 14.500000 15.347914 13.156855 15.347914 11.500000 c +h +16.206648 5.096860 m +17.131365 4.487454 17.732334 3.680024 18.122902 2.887923 c +18.464052 2.196046 18.353537 1.522406 17.970762 1.000000 c +17.531406 0.400373 16.733355 -0.000002 15.847914 -0.000002 c +8.847914 -0.000002 l +7.962472 -0.000002 7.164421 0.400373 6.725066 1.000000 c +6.701973 1.031517 6.679871 1.063584 6.658800 1.096172 c +6.330600 1.603753 6.252357 2.237787 6.572926 2.887924 c +6.987937 3.729597 7.640509 4.588578 8.666627 5.208897 c +9.571874 5.756145 10.767847 6.117645 12.347914 6.117645 c +13.927979 6.117645 15.123951 5.756145 16.029198 5.208899 c +16.089634 5.172363 16.148775 5.134999 16.206648 5.096860 c +h +5.347910 6.000000 m +6.038868 6.000000 6.650654 5.923974 7.192287 5.790671 c +6.346507 5.094717 5.770174 4.267296 5.380054 3.476105 c +4.957832 2.619810 4.950275 1.751801 5.228493 1.000000 c +2.054037 1.000000 l +0.595407 1.000000 -0.530585 2.298071 0.261390 3.522970 c +1.064612 4.765267 2.563349 6.000000 5.347910 6.000000 c +h +19.315775 3.476104 m +19.737995 2.619809 19.745552 1.751801 19.467335 1.000000 c +22.641785 1.000000 l +24.100414 1.000000 25.226404 2.298071 24.434431 3.522971 c +23.631208 4.765267 22.132471 6.000000 19.347910 6.000000 c +18.656954 6.000000 18.045172 5.923975 17.503540 5.790672 c +18.349321 5.094717 18.925655 4.267296 19.315775 3.476104 c +h +7.847914 10.500000 m +7.847914 9.119288 6.728626 8.000000 5.347914 8.000000 c +3.967202 8.000000 2.847914 9.119288 2.847914 10.500000 c +2.847914 11.880713 3.967202 13.000000 5.347914 13.000000 c +6.728626 13.000000 7.847914 11.880713 7.847914 10.500000 c +h +21.847914 10.500000 m +21.847914 9.119288 20.728626 8.000000 19.347914 8.000000 c +17.967201 8.000000 16.847914 9.119288 16.847914 10.500000 c +16.847914 11.880713 17.967201 13.000000 19.347914 13.000000 c +20.728626 13.000000 21.847914 11.880713 21.847914 10.500000 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 3113 +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 +0000003203 00000 n +0000003226 00000 n +0000003399 00000 n +0000003473 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +3532 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/Contents.json new file mode 100644 index 0000000000..bd652ccbdd --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "addaccount.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/addaccount.pdf b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/addaccount.pdf new file mode 100644 index 0000000000..af8d877527 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteAddAccount.imageset/addaccount.pdf @@ -0,0 +1,102 @@ +%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 0.000000 0.000000 cm +1.000000 0.584314 0.000000 scn +0.000000 18.799999 m +0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c +1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c +5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c +18.799999 30.000000 l +22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c +27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c +30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c +30.000000 11.200001 l +30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c +28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c +24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c +11.200000 0.000000 l +7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c +2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c +0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c +0.000000 18.799999 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 6.730286 6.000000 cm +1.000000 1.000000 1.000000 scn +8.269731 10.500000 m +10.478869 10.500000 12.269731 12.290861 12.269731 14.500000 c +12.269731 16.709139 10.478869 18.500000 8.269731 18.500000 c +6.060592 18.500000 4.269731 16.709139 4.269731 14.500000 c +4.269731 12.290861 6.060592 10.500000 8.269731 10.500000 c +h +16.238016 3.829396 m +15.145898 5.884616 12.897719 8.000000 8.269734 8.000000 c +3.641746 8.000000 1.393565 5.884617 0.301445 3.829397 c +-0.735194 1.878584 1.060591 0.000000 3.269730 0.000000 c +13.269731 0.000000 l +15.478869 0.000000 17.274656 1.878582 16.238016 3.829396 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1580 +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 +0000001670 00000 n +0000001693 00000 n +0000001866 00000 n +0000001940 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +1999 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/Contents.json new file mode 100644 index 0000000000..561d5e7e17 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "deletechats.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/deletechats.pdf b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/deletechats.pdf new file mode 100644 index 0000000000..63d5babb07 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteChats.imageset/deletechats.pdf @@ -0,0 +1,175 @@ +%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 0.000000 0.000000 cm +1.000000 0.176471 0.333333 scn +0.000000 18.799999 m +0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c +1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c +5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c +18.799999 30.000000 l +22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c +27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c +30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c +30.000000 11.200001 l +30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c +28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c +24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c +11.200000 0.000000 l +7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c +2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c +0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c +0.000000 18.799999 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 6.834961 5.000000 cm +1.000000 1.000000 1.000000 scn +7.038761 21.165039 m +7.064992 21.165039 l +9.264992 21.165039 l +9.291224 21.165039 l +9.291246 21.165039 l +9.688916 21.165049 10.026937 21.165058 10.304341 21.142393 c +10.595594 21.118597 10.878077 21.066540 11.147882 20.929068 c +11.555252 20.721500 11.886456 20.390299 12.094021 19.982927 c +12.231494 19.713121 12.283551 19.430639 12.307348 19.139387 c +12.330013 18.861979 12.330004 18.523952 12.329992 18.126278 c +12.329992 18.100037 l +12.329992 17.665022 l +15.665000 17.665022 l +16.032269 17.665022 16.330000 17.367292 16.330000 17.000023 c +16.330000 16.632753 16.032269 16.335022 15.665000 16.335022 c +0.665000 16.335022 l +0.297731 16.335022 0.000000 16.632753 0.000000 17.000023 c +0.000000 17.367292 0.297731 17.665022 0.665000 17.665022 c +3.999992 17.665022 l +3.999992 18.100037 l +3.999992 18.126268 l +3.999981 18.523949 3.999972 18.861977 4.022637 19.139387 c +4.046433 19.430639 4.098491 19.713121 4.235963 19.982927 c +4.443529 20.390299 4.774732 20.721500 5.182103 20.929068 c +5.451908 21.066540 5.734391 21.118597 6.025643 21.142393 c +6.303048 21.165058 6.641069 21.165049 7.038738 21.165039 c +7.038761 21.165039 l +h +10.999992 18.100037 m +10.999992 17.665022 l +5.329992 17.665022 l +5.329992 18.100037 l +5.329992 18.531050 5.330510 18.814316 5.348220 19.031082 c +5.365296 19.240086 5.394984 19.328056 5.421002 19.379120 c +5.501056 19.536236 5.628795 19.663975 5.785910 19.744028 c +5.836973 19.770046 5.924943 19.799734 6.133947 19.816811 c +6.350715 19.834520 6.633980 19.835037 7.064992 19.835037 c +9.264992 19.835037 l +9.696005 19.835037 9.979270 19.834520 10.196037 19.816811 c +10.405041 19.799734 10.493011 19.770046 10.544075 19.744028 c +10.701189 19.663975 10.828928 19.536236 10.908983 19.379120 c +10.935000 19.328056 10.964688 19.240086 10.981765 19.031082 c +10.999475 18.814316 10.999992 18.531050 10.999992 18.100037 c +h +1.866287 4.480732 m +1.278763 13.293592 l +1.239206 13.886940 1.219428 14.183613 1.322701 14.412016 c +1.413458 14.612740 1.567953 14.777878 1.762195 14.881785 c +1.983222 15.000023 2.280554 15.000023 2.875219 15.000023 c +13.454782 15.000023 l +14.049447 15.000023 14.346780 15.000023 14.567807 14.881785 c +14.762049 14.777878 14.916544 14.612740 15.007301 14.412016 c +15.110574 14.183613 15.090796 13.886940 15.051239 13.293592 c +14.463715 4.480732 l +14.358499 2.902485 14.305890 2.113361 13.965018 1.515018 c +13.664913 0.988235 13.212244 0.564739 12.666664 0.300339 c +12.046970 0.000023 11.256096 0.000023 9.674346 0.000023 c +6.655656 0.000023 l +5.073906 0.000023 4.283031 0.000023 3.663338 0.300339 c +3.117758 0.564739 2.665089 0.988235 2.364984 1.515018 c +2.024112 2.113361 1.971503 2.902485 1.866287 4.480732 c +h +5.420216 12.030214 m +5.403539 12.397105 5.092596 12.681009 4.725706 12.664333 c +4.358815 12.647655 4.074911 12.336713 4.091588 11.969823 c +4.500678 2.969837 l +4.517354 2.602947 4.828298 2.319042 5.195188 2.335720 c +5.562078 2.352396 5.845983 2.663338 5.829306 3.030230 c +5.420216 12.030214 l +h +11.604276 12.664333 m +11.971167 12.647655 12.255072 12.336713 12.238394 11.969823 c +11.829304 2.969837 l +11.812627 2.602947 11.501684 2.319042 11.134793 2.335720 c +10.767903 2.352396 10.483999 2.663338 10.500675 3.030230 c +10.909766 12.030214 l +10.926443 12.397105 11.237386 12.681009 11.604276 12.664333 c +h +8.164989 12.665019 m +8.532259 12.665019 8.829989 12.367289 8.829989 12.000019 c +8.829989 3.000034 l +8.829989 2.632763 8.532259 2.335033 8.164989 2.335033 c +7.797720 2.335033 7.499990 2.632763 7.499990 3.000034 c +7.499990 12.000019 l +7.499990 12.367289 7.797720 12.665019 8.164989 12.665019 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 4588 +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 +0000004678 00000 n +0000004701 00000 n +0000004874 00000 n +0000004948 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +5007 +%%EOF \ No newline at end of file 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..a4e7eb3681 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) 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/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/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 7b34ad0bcb..9b550ad332 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -3874,11 +3874,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 { @@ -3925,77 +3920,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) @@ -4014,6 +3939,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 @@ -4052,6 +3987,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) @@ -4107,23 +4052,83 @@ 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) { + 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() + self?.giftPremium() }))) } - - 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)))) }))) } @@ -4163,6 +4168,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 @@ -6408,6 +6419,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } })) } + + private func giftPremium() { + let controller = PremiumGiftScreen(context: self.context, peerId: self.peerId) + self.controller?.push(controller) + } fileprivate func switchToAccount(id: AccountRecordId) { self.accountsAndPeers.set(.never()) 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..066c92a5bd 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -90,7 +90,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 +164,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 +178,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) From 65d364a8f0ae50c929b9892e615ba55d354829c5 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 26 Jun 2022 00:35:40 +0200 Subject: [PATCH 012/113] [Temp] Input node layout animation --- .../Sources/ChatControllerNode.swift | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index dad5427e80..1d71ea7e1e 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -906,6 +906,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let maximumInputNodeHeight = layout.size.height - max(navigationBarHeight + (titleAccessoryPanelBackgroundHeight ?? 0.0), layout.safeInsets.top) - inputPanelNodeBaseHeight var dismissedInputNode: ChatInputNode? + var dismissedInputNodeInputBackgroundExtension: CGFloat = 0.0 var dismissedInputNodeExternalTopPanelContainer: UIView? var immediatelyLayoutInputNodeAndAnimateAppearance = false var inputNodeHeightAndOverflow: (CGFloat, CGFloat)? @@ -931,6 +932,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } dismissedInputNode = self.inputNode + if let inputNode = self.inputNode { + dismissedInputNodeInputBackgroundExtension = inputNode.topBackgroundExtension + } dismissedInputNodeExternalTopPanelContainer = self.inputNode?.externalTopPanelContainer self.inputNode = inputNode inputNode.alpha = 1.0 @@ -958,6 +962,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) } else if let inputNode = self.inputNode { dismissedInputNode = inputNode + dismissedInputNodeInputBackgroundExtension = inputNode.topBackgroundExtension dismissedInputNodeExternalTopPanelContainer = inputNode.externalTopPanelContainer self.inputNode = nil } @@ -1407,9 +1412,16 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var inputPanelBackgroundExtension: CGFloat = 0.0 if let inputNode = self.inputNode { inputPanelBackgroundExtension = inputNode.topBackgroundExtension + } else { + inputPanelBackgroundExtension = dismissedInputNodeInputBackgroundExtension } - self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: transition) - transition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBackgroundNode.frame.maxY + inputPanelBackgroundExtension), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) + + var inputPanelUpdateTransition = transition + if immediatelyLayoutInputNodeAndAnimateAppearance { + inputPanelUpdateTransition = .immediate + } + self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition) + inputPanelUpdateTransition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBackgroundNode.frame.maxY + inputPanelBackgroundExtension), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) 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) @@ -1485,14 +1497,14 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var adjustedForPreviousInputHeightFrame = inputNodeFrame var heightDifference = inputNodeHeight - previousInputHeight if previousInputHeight.isLessThanOrEqualTo(cleanInsets.bottom) { - heightDifference = inputNodeHeight + heightDifference = inputNodeHeight - inputPanelBackgroundExtension } adjustedForPreviousInputHeightFrame.origin.y += heightDifference inputNode.frame = adjustedForPreviousInputHeightFrame transition.updateFrame(node: inputNode, frame: inputNodeFrame) if let externalTopPanelContainer = inputNode.externalTopPanelContainer { - externalTopPanelContainer.frame = CGRect(origin: adjustedForPreviousInputHeightFrame.origin, size: CGSize(width: adjustedForPreviousInputHeightFrame.width, height: 0.0)) + externalTopPanelContainer.frame = CGRect(origin: adjustedForPreviousInputHeightFrame.offsetBy(dx: 0.0, dy: inputPanelBackgroundExtension).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 { From 24ce0250829cf9b4c92afca1c77cef29e237f3f1 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 26 Jun 2022 16:20:01 +0200 Subject: [PATCH 013/113] Fx crash --- .../Sources/SyncCore/SyncCore_TelegramMediaFile.swift | 2 +- submodules/TelegramUI/Sources/ChatControllerNode.swift | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index 64a55fe83e..2ca2f540f6 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -37,7 +37,7 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { } } - public init(decoder: Decoder) throws { + public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: StringCodingKey.self) let discriminator = try container.decode(Int32.self, forKey: "r") diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 1d71ea7e1e..82f9694478 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1421,7 +1421,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputPanelUpdateTransition = .immediate } self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition) - inputPanelUpdateTransition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBackgroundNode.frame.maxY + inputPanelBackgroundExtension), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) + transition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBackgroundNode.frame.maxY + inputPanelBackgroundExtension), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) 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) @@ -1496,15 +1496,17 @@ 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 - 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: inputPanelBackgroundExtension).origin, size: CGSize(width: adjustedForPreviousInputHeightFrame.width, height: 0.0)) + 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 { From 36c87a0ab08719934750d85726289ed29c982eaa Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 27 Jun 2022 19:12:06 +0200 Subject: [PATCH 014/113] Fix multipart fetch --- .../Sources/Network/MultipartFetch.swift | 44 +++++++------------ 1 file changed, 17 insertions(+), 27 deletions(-) diff --git a/submodules/TelegramCore/Sources/Network/MultipartFetch.swift b/submodules/TelegramCore/Sources/Network/MultipartFetch.swift index 4f855fb541..ebe9762f3f 100644 --- a/submodules/TelegramCore/Sources/Network/MultipartFetch.swift +++ b/submodules/TelegramCore/Sources/Network/MultipartFetch.swift @@ -3,18 +3,7 @@ import Postbox import SwiftSignalKit import TelegramApi import MtProtoKit - -private extension Range where Bound == Int64 { - func asIntRange() -> Range { - return Int(self.lowerBound) ..< Int(self.upperBound) - } -} - -private extension Range where Bound == Int { - func asInt64Range() -> Range { - return Int64(self.lowerBound) ..< Int64(self.upperBound) - } -} +import RangeSet private typealias SignalKitTimer = SwiftSignalKit.Timer @@ -277,7 +266,7 @@ private final class MultipartCdnHashSource { |> mapToSignal { clusterResults -> Signal<[Int64: Data], MultipartFetchDownloadError> in var result: [Int64: Data] = [:] - for partOffset in stride(from: offset, to: offset + limit, by: Int(dataHashLength)) { + for partOffset in stride(from: offset, to: offset + limit, by: Int64.Stride(dataHashLength)) { var found = false for cluster in clusterResults { if let data = cluster[partOffset] { @@ -350,6 +339,7 @@ private enum MultipartFetchSource { parsedPartHashes[offset] = bytes.makeData() } } + parsedPartHashes.removeAll() return .fail(.switchToCdn(id: dcId, token: fileToken.makeData(), key: encryptionKey.makeData(), iv: encryptionIv.makeData(), partHashes: parsedPartHashes)) } } @@ -392,7 +382,7 @@ private enum MultipartFetchSource { let partIvCount = partIv.count partIv.withUnsafeMutableBytes { rawBytes -> Void in let bytes = rawBytes.baseAddress!.assumingMemoryBound(to: UInt8.self) - var ivOffset: Int64 = (offset / 16).bigEndian + var ivOffset: Int32 = Int32(clamping: (offset / 16)).bigEndian memcpy(bytes.advanced(by: partIvCount - 4), &ivOffset, 4) } return .single(MTAesCtrDecrypt(bytes.makeData(), key, partIv)!) @@ -447,7 +437,7 @@ private final class MultipartFetchManager { let queue = Queue() var currentIntervals: [(Range, MediaBoxFetchPriority)]? - var currentFilledRanges = IndexSet() + var currentFilledRanges = RangeSet() var completeSize: Int64? var completeSizeReported = false @@ -616,7 +606,7 @@ private final class MultipartFetchManager { for offset in self.fetchedParts.keys.sorted() { if let (_, data) = self.fetchedParts[offset] { let partRange = offset ..< (offset + Int64(data.count)) - removeFromFetchIntervals.insert(integersIn: Int(partRange.lowerBound) ..< Int(partRange.upperBound)) + removeFromFetchIntervals.formUnion(RangeSet(partRange)) var hasEarlierFetchingPart = false if isSingleContiguousRange { @@ -629,7 +619,7 @@ private final class MultipartFetchManager { } if !hasEarlierFetchingPart { - self.currentFilledRanges.insert(integersIn: Int(partRange.lowerBound) ..< Int(partRange.upperBound)) + self.currentFilledRanges.formUnion(RangeSet(partRange)) self.fetchedParts.removeValue(forKey: offset) self.addSpeedRecord(byteCount: Int(partRange.upperBound - partRange.lowerBound)) @@ -640,19 +630,19 @@ private final class MultipartFetchManager { } for (offset, (size, _)) in self.fetchingParts { - removeFromFetchIntervals.insert(integersIn: Int(offset) ..< Int(offset + size)) + removeFromFetchIntervals.formUnion(RangeSet(offset ..< (offset + size))) } if let completeSize = self.completeSize { - self.currentFilledRanges.insert(integersIn: Int(completeSize) ..< Int.max) - removeFromFetchIntervals.insert(integersIn: Int(completeSize) ..< Int.max) + self.currentFilledRanges.formUnion(RangeSet(completeSize ..< Int64.max)) + removeFromFetchIntervals.formUnion(RangeSet(completeSize ..< Int64.max)) } var intervalsToFetch: [(Range, MediaBoxFetchPriority)] = [] for (interval, priority) in currentIntervals { - var intervalIndexSet = IndexSet(integersIn: Int(interval.lowerBound) ..< Int(interval.upperBound)) + var intervalIndexSet = RangeSet(interval) intervalIndexSet.subtract(removeFromFetchIntervals) - for cleanInterval in intervalIndexSet.rangeView { + for cleanInterval in intervalIndexSet.ranges { assert(!cleanInterval.isEmpty) intervalsToFetch.append((Int64(cleanInterval.lowerBound) ..< Int64(cleanInterval.upperBound), priority)) } @@ -708,16 +698,16 @@ private final class MultipartFetchManager { downloadRange = downloadRange.lowerBound ..< (downloadRange.upperBound - 1) } - var intervalIndexSet = IndexSet(integersIn: intervalsToFetch[currentIntervalIndex].0.asIntRange()) - intervalIndexSet.remove(integersIn: downloadRange.asIntRange()) + var intervalIndexSet = RangeSet(intervalsToFetch[currentIntervalIndex].0) + intervalIndexSet.remove(contentsOf: downloadRange) intervalsToFetch.remove(at: currentIntervalIndex) var insertIndex = currentIntervalIndex - for interval in intervalIndexSet.rangeView { - intervalsToFetch.insert((interval.asInt64Range(), priority), at: insertIndex) + for interval in intervalIndexSet.ranges { + intervalsToFetch.insert((interval, priority), at: insertIndex) insertIndex += 1 } - let part = self.source.request(offset: Int64(downloadRange.lowerBound), limit: Int64(downloadRange.count), tag: self.parameters?.tag, resource: self.resource, resourceReference: self.resourceReference, fileReference: self.fileReference, continueInBackground: self.continueInBackground) + let part = self.source.request(offset: downloadRange.lowerBound, limit: downloadRange.upperBound - downloadRange.lowerBound, tag: self.parameters?.tag, resource: self.resource, resourceReference: self.resourceReference, fileReference: self.fileReference, continueInBackground: self.continueInBackground) |> deliverOn(self.queue) let partDisposable = MetaDisposable() self.fetchingParts[downloadRange.lowerBound] = (Int64(downloadRange.count), partDisposable) From ecc9279281798f6b59e4fa29b350554df64d5449 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 27 Jun 2022 19:12:22 +0200 Subject: [PATCH 015/113] Bump version --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.json b/versions.json index 270d00c4a1..829fc8f525 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,5 @@ { - "app": "8.8.1", + "app": "8.8.2", "bazel": "5.1.0", "xcode": "13.4.1" } From 25a09c545191ca70fe5bea0ed2f3be2fb0d93208 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 28 Jun 2022 22:22:21 +0300 Subject: [PATCH 016/113] Add manual account deletion --- Telegram/Telegram-iOS/Resources/Delete1.tgs | Bin 0 -> 12755 bytes Telegram/Telegram-iOS/Resources/Delete2.tgs | Bin 0 -> 12966 bytes Telegram/Telegram-iOS/Resources/Delete3.tgs | Bin 0 -> 17039 bytes Telegram/Telegram-iOS/Resources/Delete4.tgs | Bin 0 -> 8877 bytes Telegram/Telegram-iOS/Resources/Delete5.tgs | Bin 0 -> 15902 bytes .../Telegram-iOS/Resources/chunk2.ch2.q1.mp4 | Bin 44333 -> 0 bytes .../Telegram-iOS/en.lproj/Localizable.strings | 19 +- .../Sources/ChatListRecentPeersListItem.swift | 2 +- .../Navigation/NavigationController.swift | 2 +- .../Sources/HorizontalPeerItem.swift | 26 +- .../Sources/InviteLinkHeaderItem.swift | 12 +- .../Sources/GiftAvatarComponent.swift | 3 +- .../Sources/SelectablePeerNode.swift | 4 +- submodules/SettingsUI/BUILD | 1 + .../ChangePhoneNumberControllerNode.swift | 1 - .../Sources/DeleteAccountDataController.swift | 404 +++++++++++++++-- .../Sources/DeleteAccountFooterItem.swift | 32 +- .../DeleteAccountOptionsController.swift | 92 +++- .../Sources/DeleteAccountPeersItem.swift | 296 +++++++++++++ .../Sources/DeleteAccountPhoneItem.swift | 413 ++++++++++++++++++ .../PrivacyAndSecurityController.swift | 28 +- .../TwoStepVerificationUnlockController.swift | 2 +- .../PresentationResourcesSettings.swift | 1 + .../AppBadge@3x.png | Bin .../Contents.json | 0 .../DeleteTwoStepAuth.imageset/Contents.json | 12 + .../Menu/DeleteTwoStepAuth.imageset/Icon.pdf | 114 +++++ 27 files changed, 1383 insertions(+), 81 deletions(-) create mode 100644 Telegram/Telegram-iOS/Resources/Delete1.tgs create mode 100644 Telegram/Telegram-iOS/Resources/Delete2.tgs create mode 100644 Telegram/Telegram-iOS/Resources/Delete3.tgs create mode 100644 Telegram/Telegram-iOS/Resources/Delete4.tgs create mode 100644 Telegram/Telegram-iOS/Resources/Delete5.tgs delete mode 100644 Telegram/Telegram-iOS/Resources/chunk2.ch2.q1.mp4 create mode 100644 submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift create mode 100644 submodules/SettingsUI/Sources/DeleteAccountPhoneItem.swift rename submodules/TelegramUI/Images.xcassets/Components/{BadgeTEst.imageset => AppBadge.imageset}/AppBadge@3x.png (100%) rename submodules/TelegramUI/Images.xcassets/Components/{BadgeTEst.imageset => AppBadge.imageset}/Contents.json (100%) create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Icon.pdf diff --git a/Telegram/Telegram-iOS/Resources/Delete1.tgs b/Telegram/Telegram-iOS/Resources/Delete1.tgs new file mode 100644 index 0000000000000000000000000000000000000000..5a62b5603fae1993f8dd79acb852c97914204068 GIT binary patch literal 12755 zcmZvD1#BHL*JZ=Z%=E(4Bn>k(%*;*0%=E&{%*@Qp%*;*l+Ayc#7v}Bv{VT1syJP9< z_}Fu0UBj{E8M0{jFaLQUp)P#&;)$f1j(%XgbY@J%^t|31c{B#FkeVnEQL|J2ODvzAui*H3kL`}#%g-%e7d(Y; zrYH6tudn6Z4oM`JTkl?vD4)+0{=_%JAHI(YuHQD^H$FbVf&LG{tsmjSevjM!FT36S zAEEwl%SytN^;UkxGmhVl_p|}(cKrkoLojEc zfd8-Xi{%nsSiixshUEkK>tK$_?uQ79JB-}A5;IOaLSeUpUmMblB-Z{VYhrFETm*Wz z4ST{c{f3=Jls8Zo3T-N{5sCfYScv8m{%pjb36D5vNiq1TZu!317{G zvSogH*X}Foo(F<_KaRI-^0&_gldL`um$QEeeZKFPqj~iA+sA*bmB)X+XrwKzw(BfX zf5VMe_Q_S&{ax5{Q3`1x{_cww7o)PuhWKopB-gw%J<4+&o)ahwIc{d-oG*S0ej-egGQv?Hw6s^<36{S+yUmj-oKSAIN@8yA|YC}uob4BIgdPal+4cQwJnI7?LkJ8pZPE_>-e|85VHCQF05!mJ2#v`OYaA$L; zCq^u{@HS4p)@MNuQ`YM@O=N)}Mr~3etxFo7#x0{%sS@FeBiypYk9HCEi|2tZz!DInEMy*l}Z=5+wmT-Hjf4R9ooHfb^%6Bhp!BZ^sx>Bd-$Z7@m5_#xF( zH}O%NT2Tv9?udy35KrR^%`&E>EpRWI*ASDyWJrn2CPN0(z;`)yJ79J`waZMZjN9m( zDyoqjMaGrO;-PpyV#2TIX)CO54iwNg8w*6ar>>`%h@SpVu5G$+43U2rETo_g4d;}P zXCofmnVN20k)3PA2IC+alazXM#0zIyrIT2RoffX+l(DB8CM04;b?3;9zNl4$t>B9E z;Z_<&uMJZ-=f$b$9gCdt&hwl)=biJQiv@0jB#)G!xb8`ra?y+(kWw+!pTGjt0G@K8 zg?L48cLPZju<`PN;(_`#_MQd~L5M?iB!Pe~P$U6ueGsRRvztWrMA2asFt{Css^e+^ zKan8TMzzHBC#yK?UM6r<%~D8|jefksp%FH+&yyvsBIQnR z{K5^+NRS~#-0`Xud3V}KX75xpaxRv;f``-RL47{euXo-TOKz79RqO|&sd3b1le-fd zs2gDNLE$C@&G!jQD>@&qXT&!DN0{-&DGn@D=Y^E@ynSsm`q?z-(QKvq3ieG`M??-2 z@2hrLGB>ghI4nne9~gdw?8V9~Ok&C1u&)Gu-}89Cpfc!LI$S4f=3VLV&PR44gw*bo zL1{JQi2@1;S#`NVT;CkZYxvi5-G*@y=UORo8=B^`Z-ARjOxL@I^ad@LoYpMO`zLH9 z8)MrR_~ebqJ7W06Xvp2mHAU9p#vY?@ByH-c%(Z(Ib?V0}X_Y?-*KnoI%@B$b^Hs)* zBhg0-upCb#TnZmuf zuQBB`++dbs(Jq)}H^^e_(T|qv27RpCKRPlosO;z(N}3ZG7-EBSP~1Qv6|#`7-8>?D z+ZD2PgUQ+n%^4ii)~!+GBpR#6z%>66#%%afINB1hC7?0dg60R}Zz;1$F1F1HbS9x& zFyv~qkd9+W$^>GZi_WN=p(ncC3M@`X;6}m#R*E)fuhe+1I&5vmmd;#lfUms3r+H5M z$R1C8l9(C-Q!|?%Tckb#`N8rI)>)`$;Bm4J;e0}?nKFD44kD}EuTf^Bl<>b)kXf`p z$m@ZeB`f&V6Drn{g*lnYZhzkIn-ZH{Y$IrFD@c#UX8Navu=awp+fivlU>ceI?O=oG zgDr&iD%fJgjPQ#R%odBEboQvjBcH)5Qngq|!B}k76 zoF1!}gODkGoZA#QXxcbfE^z&($#j!jik>95k`(S?ruORi#m9jrYU*Zeach7c)*zY# zd)5-~WcbJm7&4A>b{UUJ{t{G^WiXz(F;1Eqiogt=>zl`J%j$4;o22bZJFj@ z?6v(OXvvy40-+a8s<&PtY8vhUVL;5$Tx;0)m1==&b)hZzDsTJtAY?BB&2xfZKiO4k zc#*$1*d1+wQ;(BISzxjwE8bK9_@uw-84vPrGckW&RpinNisl`dvtB42$&lW04ksI% z@tL;f%S6V5c6Vc18a2n>QhK*6U&+%}Nkq+jqbDr&5B+}F6*1UJ(B$|?1Q|`zMuDcq zX&k+H_+1aQA*I0~qttMU5U*wHZ=Smch4mqe8_=NfX*U7kNHgH=5tBS--L=^y|0ROf zP{O6b?Y`*;* zCh}X-U3}v<`BI?wK-)xkpxU|2SKVf81%^gRTFmM$OQWiWeGb#rv@MdtHOMgZ4rX=F zuWI4Vquh~7J)%1?6h*c;iinv8v&lU_W+LRUJ|8IN95i_ks8aa9#4EwT1RQev zPNF5-)N_$LfJ^>WSkCAa88TSZ*pkJI`@7K~w^euyqZg;8I69UJHuIOg1j}z4SA@kG zQcuJ`FZD*jU+!#Vb&FE|Rc~~T+Zw*Iokj0`JI%%}`?Bf#- zh61SP82BKISxzE2{V0gbil^8utbT|}8Do^7^AWhQ^F_z(F%g8)6Koz+A^#d5^*zkP zba5Xe*BW6nBl2?L?h5gKdSKfE+FvyH!TMT)c@2Y5?fm=T3&x2U`FDgj3u*@)Z#ka@ z*bQM<+v7V2SJzD5(59M$cdc#SI_%A?CQ~C7e+eDIRzKF;HVRVlHL$mgc1AMU_qR3Z z?}uf)r46T!j?(+Xa;gl6<>@@GSVmj+XuD$e*d7|zM0gVmgqafveHJN)-K-y*6UFWY z;5BVk>quhH@2CsYXbSIKrK%UEK?RLgstoTa?1`D5u7Wk>riA*{2ov>m4gxFk!&7AN#ML7GHUtYPu?JlIm) zo7$IBEG0|Og_5TyegaW{Jh9h`sngiBmv&-v;>t+K2o6g)Q@vMRujtBaLN|DAK(PDv zJu6!h#|@4SIar}HR72>oTeE2gbH>Q9&@c}Ez9BmU^@WPf6*I2+*kGn2A;D)09;I3y zP^&u;$VNp%&{`aGp5JpxqEnQVGlp&)wMNHjZ5u%O8^Qv%2-RI)LFY|((mRdsM z^5C#cjgT=O@39~3AYS`);eP%|-4l|xKc%$)i`9L8T5i+DdEVmCxlbthu%~aa21i|n zgQdIG8fV$uV*Re?Oq~nzEu4m`4?~IINYT8-tjrw&A}2F+D(qY11& zg`Q8{%f+x75luI5OFAn#5*_k*8|&S^7&H13a?V3G$4;Jw;8$My394`~Pn*{kp6^t1 z4xBcu5Umj{$I{1jj6-Vb9KbDm(~b-$bC0gEtq9AO!He>($w$LeSte@X+QZF72XDME z$a#_Qe@|)wKqrnw+EZ`2?BxMe5H;<`pQvYpz684yG&z-?ch$0oC6AN=wtFmhx#bIr zsz{D&6w$LvV#s#55S-#wg2i`aa{>He?HX3Oi5>-}Vggh1ELtiaKhG1}CG6-4c0dqt70D1Ye*pTd)|lbUPu7nnR~CVI&zmFJ>7BLa$|C2n=9o?S|v!_j+=r#x>7JOcIW9>hYZ`@u9JaT#y{?wup;PZ|n_;&TsjeY=(hBBfN#bh0|q6 zqh~+AWJaylZ-*eG5F?#^Dw_rWq3Lq2S6yf|`cI21Fk8N0)o<`qLL{Epp#RnAf-{$z zw7pT5q&^D~Vs15+#K;sPwt)xQhz9pmb|F|pA9Uc!ni|a;0&mXk5!3;+rC7>V&G}Eh ztPTUfB0aUd`BmZ;xs9n+Vh#u&Ur*tEwect%3vvWdY`gE@6+M2p9&t#5#=qFJr~H16n=r;V^72UEb=R7kGvodckw+S3BGZwgXv^L%ay}G$|crE4fC`X zAQvtfp%>{q=ag*jV5@I+CYw#mbayQ`+z7!%YDz%i;$=HiVhJb-smNSa7*mIug2AoW%{URe~Nso0P)Ax6_Nd*?= z79e6oFe^%UH`!o9fe-4A_-wfvy9R`xSZa-ql5=A+OJ}4o+n&uMb zRVfbok=if0r%uI{s8?rukb9{UXIothu=D~;nHXrp!#-3NhFZ6z;?aA!GmDbO8)F6< zohi8ZT~mv6M$SsW>N6f4Y&{`27QH0uB!U720aW=7i5DdD@C;|@sOHV<9qz3It-pm7 z?M7-jpY6)D9}tDaC<1hAo;YA9Nl@n}%9e`VZ1qFabo8^IZ zHLIMeeLGxO;x2IGnyCKCU zSH$!~Q^f+rl`T4(BwW*(wO4M~MZ~I9dxSS_Z`Ju>Rvda|$;P_cZ`(pgf-fcUiYG_a zT0Dv|`2i{zjnV#$Y3tf%*Uy8-J{-ZwBxVFV3GUvlrPtaY#bz%w4Qa)U$8rSPkc&;8 zXG`VsQ>My%{odS^Xgbndb}&m)GEMF~S(`3bT^eOLrq~kS7+ve=j3*z`P7d56=|L1a zJLm>Ph~xG!%q4!Ge#61CCGG%~I{HdnqKJJ7&CTq6ZB#AdI2 z#jdSsh4EBZH9UjOt2&27pz=93l>W*;=z2bzGKC-IO zOs}n9vH`6QJQJi0_;n)JinI4|xt5+3=BM}M6BIuAJ;^sW`TQ(2v_pxV_(d~O0HF5l z8x^wuQ%#W&CQ3$5dJV?fbeYFcJ`B;pfwS)^)W)>ibGr(c;prVen!;n%ShMTrzF(~! zU3eMa4^Pq_JMt)+G|#R*5B7Kq8s;ErYXsTcR7^ly9DyRmh~@sj5dQ8-HNIH*?`n4G z(JEV~l|HsoPs(l3mrMHJ=>3~|wB(Ft&~UsUk*Bp@Cc%1>H7FB27dSBziZK?lGoPu7;zKIywX3-(lnb!$H+viPb zxNoG+oO(&y@70}J;6J%%qKon5rrt4mEkP%v9Aa?=D^(9LvO?djte__*p?+)8J$ zK7ddE>1LvjOli#5_`n@dAyeLbELritX=U?oRn8APKW3lyYsA+w%sE+0JS+Szd?nKv ze9NkMceZ}NP(+4UuXfiIfJgb-$qQm7OMVx+sEM3+S@%xIL_h%E=@dpxlw7q*h~bI> zzV9Sq7D}~AfLts4T$OLLc(!d8$>)$jpvf#lyqlgAFJ)w@_0J5Tt9x3Qu4bH=Dxvdp>MN(`g`m%dC_>DfqxVjoAJl~85H`_WAz8LiW z0uM8H1WmrRi8*4i7?$m}r~Ev^O!M(XwWs7Iv^O6|vugu^BQ^W$EEiptZPMOM_^2K; zFpYf#SVkBn2KrWcq(a^3P#f#cj=8ur0B8~Cg(l~rGMx+%$S?J3H7E(k$0ue5YuCcl7@`GCH>IqMmve3nU9E3H?+?wGD`G- z%;?X4!z?X<9wn{t8j2WpL@V1!HE4H9%l5QXkhPZe*)B)yloJf(y$A+u#hjQi99i}@ zf5wIZUa-Dh*zyO(uobFc3c#>e6STHO>+^Q>FZ(nRDRmo@8ZnU(SmNyAz0z-&g`BYB0F)7UB;)WBbkBWmdC+8Otz@FF)um*mh1a-NA+AGkMq9~A>qk(1Tc zDE5nzhr&$C*qKSRzqt{ze{GDjS8&r+EFotfT~8{n9HS(oG8{TcKxE?B1xS)-P*jDi z*BW&!R7aL5PA&4rUI&|-+_++G%4VVgGL0F>@I6DOh-OW*TMU14LLZL?F*$k#8~3Vn zth{1lhDILyFkNj}l`Ybu36PBn1|07lTt<+O^58p0)u#_#exu!t^Gv5QJdN<6-%C7; zXixsZ?rO_NMRtgVx<%svg%fQ(P=TNyWH-3c{ez4>80zY~DNF?C4lTjryT%CnZ1|3j z#mHzRYl)6-^x7VRM&A%zxDw**Pa0Hj8lHNcrGyfummU&7E_ES0Sw{BpyTKo7(=8&Z z-0@CrW*SJU_l2;^dR!1PI92O1ZO(MqYBFb&)G|doixl#|b<_Cdu(K@`myA~cP=9uS z)EeW5I74nQfz`6(04=?W7K5dGZjc2;D={2{C)(57sOc?P{87C~fL{7^rUr1+6xq+n|_WZC>lcZWqyWxOjk}wCAGcxwvYXEP&UmrETY) zmzKYdCBC|J|1Z?e-@5BHCpTOzi;$tX02lc6!%?_&yk6)`ln8a{%sj`j`g-!O<~*hx z%n9_&$^J>N@r#Q*jhbOO+CqxA^WQH)yFs$43i}*UUe8$)9?jSxUHJ6w%lppbURZlF zHWh46{Hw3*$;S3x)-o7qSyyOx-!LtXcTRpD@WZMr<1~$Q!6TOlWH$_EE&G1GezPZO za5Qs)KIGUHwf`c*`@L`Z zL0Lu!T+N`g)>Jq=F~W-TMLRu`ikdy0+!IaAe`kBxd`3W&F7Z_*1Mj7KjLL{pGr2wy{%_b%?UC)-3e*mA6@Gz1vkNoTD?bT z2Qwb0A9O1?9t>4?Z1v~djba!aHtphuNUVwv=P>9z^ z?HD+)*AUlyfF5qc2LY{Sa#u&IgHp8a#%w;6Yqvv*pO=+|G=1UJ4G``4bUTB_zE!mS zeRKj7#usaTG5_SPJXN|kyVjWXE|}ec?T{8hV9kqlAymZYge zO(4G**1_IJ>6fU)l6x`SQyXj@-4TOnQ2c8EIRI)* zBd|qkx}>8Co8k}jwZaX9*FA)h@XefO=*dBD{Z?y_4(*0?V2;kcJExisU&9a%h3VVV zT|R@mq&4D7?y&TI8B~dWy}RGv_vRA=b!kUzO6oja?komE?i`&t8yQPgAqh`O7=8iA z_ruc6CL$VGa!rvVM6ZnyR*gg!h&f?zvpq#pB=Hu3XW1KL8qKHjWEZq0(|h(g0;)Wp z^v3<4OJXBi=hb{c%T0aftl@KSiiihf+kMZ+Xu^HM?~daab|@SWeKTrK;Lfb0=?xfq zL>8_;&R-fr4}CoO;{4O&zoe=073Q#AR=Yeb4{;?Xtc<^GA~_8G)DCr}{4Qub5{ikt z&;%VREzOEV-~*1s=xfBuJh0fsxQo)cX}2Q~Kmn`aUI=e&5^dfWG$wNNdM+96Y4i>t zyS?ihS$6ud{JV=yXWO~%>QvV?Vlf?tbfHL3%b2!2?z3n4iEyH-58Y*jadPy%K(DRf z)l5K^`{$rT`VlE7%aG8~KIyy#xt5~E0r}cLL-7xpQvO4xRBH+rvr=_Ab6Lsyyt#>~ z|L#m1kW<#q52nmYLkn`!1D!#E;FQXOGv7#5)j7DIYznKu$6cI*iFtm?KY8n9is-MK zee1%h&u0XY0MtW!>2S|YzmM?b?(3TY3MXf@KaioyZX5Dv_c5tUGOcSA+G_7mCs%ZK z@k1DW^hb2L1S*OWh?X?TfLF_fiLa|6C8&{aNcU0399tS2o&)ek)O0cZcnCLD*^tsT z3p-1tEnZn8`#jH~+9;ktAu~3fznfF$OdZ@*%?M{=g;fZ(PhUON%xvdbhmhbnow>uH zO&y#G(iOap)e@u-Sbovq@!Xnbumc4$SXX|hCz{h^TgDWrCE}_xNNcXLc<+eKGHTqK z)gX5WG;qQ8@7~6E+`32ZamnH`b#e_$>~b(2G}J2g2?hN$7J6oEqmSvLIH$JPrD(|} z#rqn0UJ~T{`sWYX*5{L9(DEws5?T9WC%hJ~69jV1qZO|FOjML_M^D{t`$@R-N)0H{ zsnPn{N+ZAfWO^rq%NR+ac6hzQj?r#If`Hh^jA!fpH*6-Lms1}*IgC_01xE28grdlf z^MAI$$6eUx5L9!JQ1&@ye0seX3#*Mzy{h0As2Gq|*#2gHpi0cK6&sRdQ?Y2&LSXgp zqPWt)OgfI8BJ+x&A^nlof5$_|i&J>S?Hgm^R#mt$K;t|TAjv?vBn}VD$h8MwG?Cx% zyxi$*Amae_3=`IE(j^P87s>=O#xE(R;3Vl78-E^;b;S7H_VMMu^TU zBH)#81H&FVeYQ`Uf#N_04Q3Cb>1qNq{n#Si8yUDug5zB>qf* zH?-=@(?f~ztzDWnihvX5pOSdMB$iiG<=-nnb;@vQLr*aC>MX4C=IT7Wuno~=bhnp> zFYUM<#rSlc+)LOd&u2`ozmUua5X7uOJ5EG9zA|}35Xtdqfa>ntW9MXk1=;MdZg)H1 zE4Ml)oS(=iy~%ew@?>#B^w9FpzTG}o1+Ua{D8&$WyB*Od?&r`-(Ke0)8rKB9m!V8& zGf*=5Q5*e*J>z1V{2rnGiTSVvyfj(;5`D;=5^+X5q|4&IA0^F&U(V=*F&7NT0__WW_gKU~p5Nq=uzLM(B)HW)?)`rk{~r=qeUs-jHsdSVa?DUz5|Iwb zEgZ2K5{#Z)85VrC^F@0+|L7ImXb$&&KsnpZ%k_V7oF}~mO*V#myE~un=J^hLby#S@ zd3RX+t4XvvEXe=)kNx*TvdKRJ@Q?VPqW^N?-iAkT$?j2P{%@!4WPU#Riu3_BZ;Eqe zmYe#mM$Sz0B0|x+T^>is+AtFYKCodUiu|8(>YSpN4$?%jokL69n+heg^9dr(< zvhC`@E-+2S+iyx$+eM;P4`t(YQ~VwaCgnQVVyAo8AxdwoWS3mc`sc{~mo?y)kyD}} zOqWQj$j*|c5&bDjRhd%iIXEI*-r;3TmqO|S@25M#tBwCHQ!OF3YE!N(KgO0dUq|Ks zBUDoq^~YrY)Jmi-cWy%LpC(O+{|9~l50d zm~Dxq%d@yuC22rk-7rN%q7XLN{`;c2*51|k z>%O+m!Oge&Oz%I`D#42;XtmwX@Aats0`K*r3 zlN?!*D~dII(-L|nrPJT|G`+j=Z(DK=LM3XX8#F;d7W(1V808R=QW0lIvxyt!uuQR+ z8UYLudU_YAu@95uG|4d)%PA7;unq2qolJ^&i-x9GR+*@~j>107A#BBK2oHrg#Ua&W zAq=U&t5-YHMCtHUg+*?g56<5W>Qq79-?Z%-vo+q)L$+ddv3c&5whDFLA$`+`cWbrF zZu$Hx{oKv1`@cx-E)!XmuvexI5YQNwY=uWxbUk_eDE(YgAL+FG5bU?YWwxERQgEa>Oy}p3n>C~?rTU=<_zZ5b2jt$uQ;Uh&l8R?@_!OOHpS=12iUKQ zkSYo@=5Umj@XiyM7pxu!{v5W+6=tF{Yur7e>zn#9t~h;*jN!Lz)UqD)O#(|lQ`#{j zkB0-V99eh6X?M>$$b$$JgNVe34J-66Ha#Wz^(HN_)7Qz0K$P)CY>@^Ih$x>`Q>xw* ztkI$8)Q!{r|1ppHjP?aOr2%zXh&diKp&=b@JE%`fcqTej+M(-We@JDhJG3K7H+|Y> z#wThrVZ#^3Vo87QLb69xhyS+IncbnTtE&8VGdv&hU}{IzM8}+Fk&z)Ce3?+{RVA)p zLi5^5aGN%|^HW=H)lNMhpn|6CYK_b9$wf*5@g0(++=a%pc#eRJldbFKyjKEkNTJ+N z`0VarM?ar3XN^VY2ilw(SwlU1_u6J=RrRg`%9XXJ)^IoB*01ZjFb~e2>fQLtuva_I zx7%+2H|H)y(u7L$Bi%SNSIvQ7j{AX7A{|DcFLCvnW)3=TzmxbDrKcr+rFe+<&{ya! z?KSZF4&TbkLZ9SnF>%wwiB=;beicB+c|talw%SkiEv-Zf3}$~kGqP#;I|x$@RrMWa zGJe>BdZp%TpQ1X#s$+tApaue-t|Z{cqRGMrmp~@NWTtV_jdt;#EUvXI#95A7(+w{XEGKP&of`*ZH`?5!&Lu1V6?BskIanNBMZ-6_ zD3Qc!eRvO>vE}OPf z?9DeUR|icuKY!oKeYKdIg*lr+_sVL+}g;as_kMEvhMSiSG;>C|c{ay0=P$N2P^oCreI_+H2K*x|y)bu`ar^Y25N z#jj6=&|SBz)Zq;F!5hljoyrCaY?Y$DH^~fbFwdHB2ZXa#0yi>;Pc>iKX=kH#DbKW! zYl#(*cVDLYtGv%Nj{S6q%3qkpW}my?%7RGU$X$pM#WgBTsdgE zuF!v<&fPFtR8IaesmrSHO#&!oswdUEDkmsOK?7gmgWe_%>e8~LRIn4{CYLz{Q$x$t zakEu*;APLC=itgr-%kZEl&rEIJp~8OI*sVIYc4?mk3z{Wq2vSG80N+2_A^&1aUD!s zMlx!;gLi=O5GR>>XUL%{*pC?C*~E3vAL#^~;e+)Zs-}Um5Ja5h{o(8ZzEmo|Ehb%| zEF&iaHe8@(L5xou^A3~FrH=VRtU?Snp?}OhIYA3{{W=pz%ac*#YJ^>E!hS~o-}m`9 zFAfS5@E0|0`*Jh(kYAyikj9gvVRw`d-}*}gnOTDrCwmJ7H}4mH8N3;^gq7U$yY?1w z;;ZY>-IEqSV!egki+i*0u+yEs!bnVH?uy*SAjr?dcgFKKa==}VhEE>TAvhQi)H*2q z2NJf=z;@dw4VxE}+V`+khPb#_pb6^(Hx6rE7Ep^XQfL3zHDt zu3bcMV_BLt{@+$pmZadMcrh(FQ+q@yqfz182@#12nG){j0Qr)@1O}PjLxy_68_jFf zFt@Jg>Ys=D<24)w-=zvQbd;xlPEVM0WzP9)>?NR0i z+tP*Z&)3j%Ht?_B3h&$L0GOm%5l-`j_ygH;H13}ZMz^wm-oSDrOiXVuTXqJQSIT8K z;n_SdF<|Uu9xtDFS&C%L$OK>m$B@BfhN;7#*%XuKiqKh|%Ys^nNRPRTZ*Jzlw!&4kWR)^Ns QzE8AX#rC2s0OXhd1q#sd`~Uy| literal 0 HcmV?d00001 diff --git a/Telegram/Telegram-iOS/Resources/Delete2.tgs b/Telegram/Telegram-iOS/Resources/Delete2.tgs new file mode 100644 index 0000000000000000000000000000000000000000..d17ced8b0723cc3b332781d68e60f05e84d07056 GIT binary patch literal 12966 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 YFBJX;UJ4W-^v8EfIHh-;3Iy2y0Z=DWBme*a literal 0 HcmV?d00001 diff --git a/Telegram/Telegram-iOS/Resources/Delete3.tgs b/Telegram/Telegram-iOS/Resources/Delete3.tgs new file mode 100644 index 0000000000000000000000000000000000000000..c65577a62a679f028c313c05707c8915f3368d4c GIT binary patch literal 17039 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 RPT#LDN^RUf=qHdM{~tD-Km`B* literal 0 HcmV?d00001 diff --git a/Telegram/Telegram-iOS/Resources/chunk2.ch2.q1.mp4 b/Telegram/Telegram-iOS/Resources/chunk2.ch2.q1.mp4 deleted file mode 100644 index b513f5f83d10d3deb32a930c4bfb7f46f79a32c9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44333 zcmV(yKz001Cnba`-Tb8l?`00IDMb8l^Fb8j+Xc4IMZa5OOh000PPa%E)z0H~d9 zWMOmw000nYWDFil21ckT3*J}t7v;YAB00RR*318YDzvLRa zGq-U1&c`kL6S@5mVB1?RI$A5KQt_tMcJPvGBg9NUTM{iqCXx=-w$TWo=$So53=iMp z^plM&bjt3GK>K3!(sX35V7}T@T=Ef`%4KiTf46*~81#=Z{NtSm7|~!>++aaU8bNLQ zO}-!nW8Yy=K<#P-)7z2}V`a8mH$CZgXo2tT>#%4S-KI4c4uXk)x50a8SBF*O*wtvm30HVn}!Fy#E43l{x@#oLw^=mXznXQ8uwN zdWd2X_Po|)2!J&T;`+F*N)@SX43+bkmCmK9OQo>~q+MRk+K*X=p_vqI6to5w+Cn?5-ypFAv zL$^jsCJzF!eGIRV)m2$Csa5Mie#@R2a>^fjgz>^d|MW;w7-pHRGhGvak`<^pHzbuh ze#iRj?#L$IG*gO!wW~E!_Fm1=L#D_YQmPp^7SDLRhh?I+yVO9vo)cU=DnfGU?&-4U z<}0+$o8DIeg^WreK<|lb!76tjriN#)_5ecr%m3zD#VFKzXzWZ=HOh3w>H%? zczILB!=NTuG)SX{SYMINdPE>a+zrD{(uhy;^2zY$JrS}QMdn@ReQ6sIqYV{aHG+t% zrHpRg>`W0~#Rd+atfaylRQKhO9dN%n)HwwH!rhgbPY8C>cIy^LoH7Ltlx!732cBlg zFbH)IAp(db7u(^%pP@HQ)29F-KWQB#gwiz{&qhf*jA#TaHEX^Jr}}|Oi`*O8HL@7I zP$xv?4*|Y(r(N*sMO|TVO=GkTf0(g7URKr#o$G9?PdouX&!+0LO0Il|Lh^|t=b%AD zR<-}WYtyA9GWUE}T2@Ii1v~CAIR0rRqJhiCP2kiRpMxr}eHQtWdw5D?5TWcbM1tBO z@Fj$H=r_Jn%jI~M#k8n`M=ncoK_S*;$PJMtroW^epg1)<(tAvu&Tt{19Rih zZ%?Nemw)RB_6KKyOo=^XX$F$!U=h*qIu(~;yifc|1@9xM;_?98${oEi{V`JTLmHn_ zsJ{^IkJ;pq1n)j8=PlcZQJv)rCQ5GKB|u7MXC&&N$KjhjhkwCUH5>6Hu>`MF+(}zmL zb6*D1FS+RS@cm!mkcyv&wF&u`MZrfGiRZUUOpYP!Gq6_?={Sw7=#f$P^$_M za+gZIHJn|>{P0@|T}&?)_!gYTuuhb$@N(F1dYcL}dJqF#jz+$pX$=bD!WT*+v`6p& zfo_Z;g_gJk5SDrkT1AM>O@ZGK2b!?766upqzflCMr`Jlq#d4;l-o&xfAS|8 zTg9|ZC0J?Kd#)I!!&2F#J#|>MtbQJ=$@Tf34;R_EPiAaFz%-u%TtQN5Sm`9KV4kyko4LMG|uASk`6Bl zRpo|f1NdxP2XYMTgQm?QNs2#`T}(D~r5~skMGZK}#O~J6RHR4Ixm0erK5o(lJuLn3 zqQlSVEN6+kV&)HVsey;s;14nJi)$x-pE}umM^Ga4KzDelyGBCz*YfBxX)vcHrO3V5 z0J+momZ~XCe+N0wPvXj!E6DqpS-R=!`+457R>o0vBK$~C!yN`jT zs9{+jy-k4e%A(aw!p2%Gnqj_MtuM(ypy0G%2TqoH%%a;NBdI&t{l26p*7&E2*=et` z8^Vor|2&x^=-JXRREkUuBF z7{d2iGyWW(ihuI$Z`B&(+S|YP8P|xnU=;oCstaJcgIM_cH4&xQqda6`HcD^RBG9!Y zo3f4?7%QYpijCpBDBJ>aun0?U{@i7|m^Dow4`JONpUI;v3Ww{T=0)TVKPr}`sj^;Z zS&ABzarsM9KB;CdwSx$2Fc7cGoU&h{_=u0R5F$zSz0fmVDlM7ara+YW7W7`Q=u1n0Ik_ywo469n1Fm)oDPB?3ZI*Hi{;5 z1jcn9etjE9>c1_z=gpbLRemirmF`Z=-6kpkN2R=}aaY`ZKk8MtWAiO@@vZjC< z4p;3^a{NsRZ>X8%@8sE={w%N4W)OveReS@lwAB^8+g^<3GWe;j8gd|syQ0SZqvY0X z+sji3{)9p^ebA`eKKjO&4DQt%sR_=FtqsCgmfdQtqODfKR4AqZpQZ|xx^irBom9BpDWmhg?6ORsAO)Um8JNy9Syb%RirSbIFD*tRUL26CY3K@G_j? zBDjVEyaZxwAVR-t^IVEUKYjXE1s@@~8i9W-dVy2U>|_nHoKj(=S|-`ymiesQdJU&A zG({;}BO2o4dY27Dy))0!=&ln3YF+_)f&$;s75y=#^@ zZVv)My?S8TjB23xU!>V8h~79_d>_wz_RPbL0mOpPb@{Zl{vbQj{U;mBzWxHAt?F-X z>Li*#5w8nISAC5K>%48O%Lb>83RxUu(DT4?J4$IE*U~cgK=u`_w700|op3ydV6WS* znvfxETsUX!A!}6XYTJhSY%F&FxSSV;lF(bU({%IxunhT~J(7DF@*7>(6heSFreFCs zCeAoH4%lH6N5ptx6Ket`n1{nE2cp$A^ryMb3Gp`-eFD0YHTMz+g>tbG`K;9DA8{K- zK24!BWx5ff>GybgZyRDwr7LkoM;u1*H7t7OfiCD;{gaJNN3D{)#1lEfD4^`x4YOC)b7odp@7r)C7<7SH+0~`WUp0Y_p=;r=_;Vw4 zf?hIBLyRQB2>Fel3B4Q$U5V5T0^|75j!i@e1!1;P!^@rwV(c}ZHfI-}H1Pq9{#(%D zaI5a+q7WhAe%zb4dM$4ukASU^=a_6mU#auwI=A{_J$`Yz6I+N$hJmlw9^Q82+*mtg zC;J4$vzcq7CIof7FFn0IRzQj{(qbwRzt%!iRvqv|xun4a%qHkMK)j2;cv z+hUGqQ#;pMet18(t(No+Qo}%{uzenO2&shV=;D=@DTge-)43PP4p!MzBb)&)I~2=u zbhca!obSZa53x~4d{>JlKkS#C5vnBwd=dl?N`sE_daqD=his+f!~BuAL>Xs(X5?yx z*pciLGwypNl>=4(b+O(ZR8p$H3jO=L=&?0U4RvuJiZ6Ko`K1&l^(lu;);)2adc)Wt z2+zkE1m6<~SZ*_MSx>j25lU0)lLJv*Z zqFBGqMNZiE&WUQht04^Vkj%tzUCjwmoe#W)X*@Aq*dLIp%b%#>UsHp4`z3u}XGE+a zV0|7omzX0n%lcxf4F0FF@jA8zcq?smo$>#sG&_xL#j6($t>$`WU-I`KdV>d@j@UJA z(>4#QEV;k=mCfrx89*t`|CDcmc{j%oc31BACr;~-cM=*oCN>Ky9QDkDkuyeOCudbk z`g90PjKdm5G&l>bl#4!AP=oS3FiD1xJR3Hu!L^S71jk5%yPwN;%*O>=AfgOFZ$8H? z0a?2p&~$vyZEdM; z9txl>a_Un+hWQWZU~c%AfU-rFeLtf2$P<(X*U{{yTnnWF-Wygyq>T-c4!bcKjPwP-PwE9nZ<7 zAMsK(m>!d=-N5t#o)PMn3&P-^5mKc1(7U9jFOM6%HtQ85bLJb(sY;|{JyN+lLXeL! zTal>K|ADa|c?*d+xnE0n;vEN}RjqxSzeRK4i6BUIMEpIY;q&B+x#K`Uq{Uc5nz2Yx zEtFyy#uMn9+qr^2;#5pKG-gTY7kIjfrDzjyW{KC!?zI-5Pf3ot<7{{QnTHP8VOJ|QrU>z)}GD`WmGdY2>c zWOT>qgGoskP%W`kyyM}q@2Jr?+c0U*Gn8`&@#zh*B{kmKet-S9Ptn>Iooby+@*uv#JzsF0CY|-QisUL5n8DpidMwv1x5`HWTp^E@&nqZ8x@a84 zGSE?$w^C=mxTE1K)O|3w1Icladwf+)ki-=4uj$w-5Yoc)MEPCO988-!eGovk>JI8^ z@eW{+5%*D5`2f#lvV1tNf#zzp{#3N#xJx@Iy*CF=)5h9`@N zImum4ZK8&i19jvzi9cgAX*B>y%nQ2#n_l$Bbk=muxFkq01h@=pWl0WYm9y+L0qR<9 z3t#7wzBcRs3-$gDJ!6dIpa370Ay`jmfQ~?BRaUE9<|CvHY85=d}|!M>i=O zuqoJe&{G};>RDiYSq9XPI@+B)Si=^=bt{WLY_SUILp`;`B`xMsi7fsCU(UHbV-Yxr z%51+1$H~>mZ_Df;T;YK6Ms))!v(jA`v%+L`D=eDhkV(EPS$BuBogyavL$$pF?<_Gk zX8b&W(f*}(=Ohh;G#)2dHGK;E&s4)tt^10tQF|^v(e;zmAX3i@*EUp-^kC+Lbe?z6 z924L0WH-4<<)sy25E{-w_2io?^1H%+W%#=>b@pBic=ZIDL|uo~pXl#{n2w9;PFyN0 zHJ?o={Yu4ygVfl_y5i8dn!Tfl!xU~tekbS!RxnJFmAw9rV0l+)FwV(?8=Ji2Of}x7 zwUIFt2uey-X?DK{e%taN?CrD!yc(v}(|~o6O9F<@HWb8+)n}DC?^G8aK1?U*pmW=pkn7m z%VjuWPt%nd2}+fl=VwvyPtxF;k?8d-6LB|=LIQl`*uThbn$gubn$VrZhq3!9^}(N7 zi9b#YFrUJ1MwGTbd$gSmIDX{@KPYLdZFwu(1_m#J^r_D)Hy@5->G987=q*w~)V~Z5 zV5na1;6EccDPG9IRv15CTGrz8qfbC?pcZ-WpCDd`ur86cpnzIpS=j=I89mPo6~W%U zwvwbow4KT}HgLAdz@yF!i|k#?(oxW8{a-3~X$@nxs)J5xq8;NEHrZp=ziv|THA^G{ z7X+qve8g-51U*Zd$Kq!4N4~nLajj;#QE9iFk{xiTBU6BV?enE9&VDjv@Z<5Ln-U!E zGIc1~psHfhc>58bAeAmpjJS+U$m6w*W54I30i&OKCg|Ql_#dED1FE;EfTqCFB$1#D z5#tvzceAi4DRXD3p~k{mHhmqhFm;ckMq%!e0d*p0OP#1uQ{ULch&A~UWk6K~dY(r~ z@;m`zp-R6%Xp1<^bbOA*;V-C;!q68P0)l$$wG?vaE1aUle@Jsk6Btzv z;;Eb~Zl{5H(J-nWuIz1oYomXX$D&tR@;b1*=N#l_drr<8QK_cD=3K}vySHZjJyaAZ zx%=ox{t#5l009my+<%vt4;DnRKXMeGRvIc-(jzslhq=$urQS)>Pi(f&K1=2LDtHPA z>J5=ZP~22h_#jIm?@*4+*Q7R2$|zXp^ZmqYA7S6UW2i;t1Ace_RkGa;b)Q(e)>P0- zFD~6twvxv1Z7Q|ulK0I{V!Nu2J*5HQSHE243fhC?~O>f3l1Weu@7 zrPN|Mf45zkth9LgoIOmfbvv}hz(6n+vUsz*o8U17 zF)Oskcu;i<@DqEk@pOQo!?sBTS zi1~V|JBC-}NtO+)utIdp?&UPZ)^`1+`*f&Lp)H3?P!oI>{e5Zmruymh!7#_Nv@T%L zkX%Uo_n<9lyS{;lJUf3zng)j5RS3;plW|8xRw!-O;f<0C1;Xj+UL#hbqeU|&dPLea zrCih@7qi7uzUKZ$cK6>SnauvokaPlZfCno|GG)Wn7dvxJc^g4XTr`C|p+@HmYc|?& z8%^w>Ju(BZ>_SZ{9&SZQ%k?tZeKZvq2EM@6CIh;-vs>n+GF7UUw5gS(47eeSu5=lJ z|I(Hz42rG$jT)F42=l9WeM_6nUjs3FugTBYkySz{nYswCNN|+~KIrJw^BAE~k+SaG zWr+>G$I4IBExsTjC-zkwX>j88O6^%iVa&RvV##NLycHZqhh-0{x_Rks0_>c;>)vM)($86PU|MMn%95R zW?C6u3#WP9rnsWb!vcR%YWkxDR;+SkN|%dAAK?mlZfx95*u^j>zU@5r>0<6o5mN1Y z2UmK4`RUZb3mU`rn^84bgIvg%$KL_^B&s~77245~`-LnYr%7*f?yvl_=@ z8cXM4DiB+Gc0apR`?3O9y#WPmCsgJWJYfe)k}fPo@zyLpkT?h8rWYCg!T-Uhw*g8!G+V8pNjOJN8R!h+^rzx84Sd)ZmU%c&fO!n06U$e9ArN& zCeUflU--Z)23kG#?#37XPNl8me7#7)d=smh{kM?5&lUy_^&K<0*0&lN+Vc8vM;mfesRdNybJ;^}dG4!@CPAr}-r3!_V$|I0-T6Z4 zZ;P&12nFC>lxEh>z^FWCn;X0QvABYP`}O&KUVQ56sbx{ldbsZ7Tz zmHDYV1aIqr2GsNJi!683%-^0br=YQSGGuI2?Q-xfkeEV?eo)p2L4d6cBFkoknO2x_ z6J0rlDg1@(DavH&4kmTFq7SXf;_l2N%Iqoumw95S>Aj;TZ3FcX3AXiGH<(!sm~bxZ`IS8S%4R~(=;G{2h?1>iE(VUU`e>iehxkOhjh}|JRLft zlUH>#%F^i7%c4Uz8ks!NK8ZOuo-I4m>fk%XWBN3G!ZZ^(S<6Lg0sca7L2NrKfC7tG zcg*R(Hc(VT5-I6VWA`7!MNA;8VSzo{FgZ6VHI=mw=Pq(G@!rL}aOExR25r;`?U~;R zX9dUoz^3|c!a&|QPGH7LdiZcK@!p;iR(JJGUTBmV_&x!Ua^@1;paiKR^P(GTl_&#} z_P^iT2bg;MFFtRFmsZ_4U+8~8nTv8#V$krMo0G>+SE`=ERlzmA;^CLtRaQ8fNFz4d zkikZEzNV9*T*yfB7`wkQ*UvQ^KL7~bkXzEu5GS&-)t@~?a~|e5anGF}R}-qWp~5DN z=1*F3sAKtx&B$BsRuaf(wdzF^hi|_#;YaSehUkl5#P@d_&kup&Fv6xw<~t-pztn7B zH-*z&689PnHR%3Ld=35}Lh*u-_9WVFU>JwiP4a1qk1RRsq$93b*HgpL1EAK0F-?m?O2R` zhQq;DKu&jz3l4+WCVaLkF&e^``iCTi@SGOJh#fI(MANRerNr-mz;rF_K+Er&`0pa; zccm4(txi&e9j4tacS)-blBPM6VM$8x4L#93S(&*wLZOKiQk9QF>x@^=NmE_s2j93HCZXy>T*p zx@6;%fwi0=z{#MyrkInW9mK=+P(eVjoRk)em|54v$ulSh&mLt3xx~I|2JQoFy5~#8 zK~Lnik~d9ra2eGi$#OwRfZTNA3*itKMb1xorIAsE?`)=DUfHdm(dK!rXIc!xrllN$Wc7GZAj0$~N&w1Cjra;CHt& zJ3=M;ya`fh6*2e97S4Nyz}Cw|(LmYG25hrV!jYv+y%|53UK2tv388`nQKwzPAxgvb zZSbOp=lib;RIhO*TS26;uXnnY37}3)6_UqI+iI8(iL)g#XK5YqpIczNmck5p-fzO< zuk)~~U_mOY!*NaVFO5Op0TC}TVgn07x}1r=8L7DrpmQZ{hhm1 z60Su2Kx;nyWa7wsAY^%KMVcn8D}3OY0ittYOij`b z2m|uPCZyr3Ez%#EqRk>|_SalC?Q_ygUKN$x@Tv>{lU>La{kRg#l5^V=RQO-CITS>B@{!asIyc}Pu9$ihtjc9sFRp(dV8 z#{t3g34NKgXi`sK=P)JJXiOeFSK;Hefctv~DJCMLhrqWM4;X<66HHUaHvv;D1;4*4 zD56kIf_U0wIr1Y_=ziFwC@3WnX@T|c`oGAS;Y^*eU3NAF;!ZGm0DX=y$IrAAZ~j*} zq1G9x{3ZfhsFM(-8VjEk=&8^H?Be*(m9Wf5GS9+d-BS|;0oqEaC*LZ;Lq@~(Wd%%$ zg11V0?2>SKXy-oqDKX2j0S4)^NO*!4Mz5mf4-siHRp3{FUI?AHgPcijA1NNGPEZK_bCVQ4Y1Z zPabJk#q;81OH6!8&Cp=s`PQ(ZSlDn$Bhz4$ix(i5B;Nde1(2E5p{PZ7kX$5z$pg|_ zQN-L%@i&(;XOaI$t&7es9VSlZ>Wg>V?(Y5p_#gB;;c`8`tZ_-|c5JKf0$BbP-!$wC z=SbbB%3;a>ZIPsxV-P7hp(@eW>pn%43mXOzM^%k082cPa|S+ z_jv;d6P5Er6Usb)Q5GnHO1@<0 zthMY$k2~t1kShC?K$u=&AQU}RkZ)SEtf_(cZjQLN8l%P#R?DUO6O$`B86gUU&Inan zl=`jpmaXde209^ih=ny&8FUr35A}e>OY*F<>+FRyn8j z1Kxk+(kX6E2|5$#2Qy{xX}-_epnR;EK6i-K`j3`V(41Jxe$5tW z>Ge9Fjp*(~NEJG2x6GN#ZLVjTNrrZPQ@n})gjIueW9&hlT3Y~pKOx*6cGGhC?d%y?k-kRLa#fJFf^Ehs(A=I>HK^v_Nw}C>Z;9boF4>L3hh;Ko1C$I#b#5R+{>M2 z77s=@&`t#+UZyiyh68jGHqMbG!PQdDX9!NBh`V|^Et5#%vF7*@zHEa`gip|Fh&$uE z1n%yE5jcyleysD&ki%TyGJ0(GkqIQT;$2?fMAhZ?@EkS7)uVM?357R_^ItD;ak#nr zn`#YjykB|Asz?yV)^C`u?LVflj%Pv?w)$YQMk68#)0&_Dw$!g=Z>^p(+cn2P@O-j) zo8*uRgxst$Ic!A_ADDfLSlugys&dmuHOtwvjT$YZ${x{?7#jd+(I6Lk;uwcIP&nuv z$QQJwDfi&{ImitTb(q=3!kmPN0S zoFUdFwvi8a@|0Y<>H=Bk?XM5-%+eI%?|}>5%n#wq3aM-uDC5$Q{;zJ_&WLs-94a=E1)IcWFY5&0p~U)#w6Jdrecm}J5LDUXQG1|$4Xd&BB+}3tqf<%jO|*Hc*-BC68M*IJCkS}c?K6-~ z*tnqIM#55-wE33{04aI2_ABt;B+O|!Z8_giksqo0vzwvln_xmKXve6^EwY(+LXvIH z1qy2i3;K}FN=pX9+L#*W=$upGt}`hIH{}5Nu55TIUmq(OcujLbW`VY1Ekc7}3fh1r z))FL+-upqo9AN!SrRYp9in^tY8%e&ohA@vMEXoH=oXQY8mSlfpYqHbt2nugQ7Q;Rxgq4D~)Fs*(y(~kYy4&=<8?PE~E@9}>iSvS^sI0I0k zk&fcr!D`3)Y<3b-Gw955&ZcTU^n`RZi*lsyWmsdgIoy&-2Y`+gQIr zPQTXc*GR?LmoR}Iz8kj?5jS)NJ9f(@&#Zt8GLFqN*8Oto32EO+wb1*ZSAMpxQ#5jE?5fe;vuV9nog!Dio0cRH? zUh!S0Xu2|*p)5NtD2)npT=sdU9 zjr28ywVvn0CL4rDzC_x~#p}zHSKyT2r*F*(I=(8s9`jv}eF3P9_?+=(u%CXd8bzFr z{jo`S^+EY>?`FRPqK98GdmX*dF|la`gz0pXK=30rRwi90$F8Ed+Cu#lASS#DL4t51 z?#e@Z4Vg^D<4T5@z>!g4^G5`)ukQ#gEM^OMt=O6R;QR@usOXtT*cRbtJV?Uj!*;>5SDgk-01eUXxc(FN+ zK@@CIm_Z_p$D}@ns3xS1Z#SPQcVh#={xQA1AX}DqF(iU*x=Y5lFSa)chm zELA*s<2x{9cND`HGJ&6TM!6+7a3BQerjv77mkeLNS>rd!A3_Ra{$coRnJmOHYEeG~ zV0F57fYlN-Ww>6gBqj`sl6aIb=@N9Tj!al5oF=vDCs|_x9~_nqikZk&YXERhEP7|S zkJxv-^Q-^hO_QnIL=tIK@SrI_&=l;YWgal8PvVoUYpZi^C+SDk=u-B2BT9dq-q<@a zU7T9F_W|??E0r1Nbasbe96p#;K8}{2W$)osKW>`=2LQw*@PxmB*NFfgIjE zTq$LWV|RlbDEzgGH{nknczM;&J7$ShdOtlV**Vtee~6;oHA~E+wfJa@Y;y@HIa@;S zaN+uL*WBpKCjbZtt~Su>ENvHp`nK&i1M;RRZP~Qf{CY)h#*1V`bU;}FANuqr^+iF| z0EN~`h@4Snb+OM}y5@+^G=SgR?N7;N>cj7gL#ZI_z*aM#$RPYrCT}SMV!KYqJi>me znOmIn0T0^w;13dNG5hBxO(&yPKq%Qi9ax?pHJsiY$L9BP0Emy~4imeuqO8vr20^q> z;%NS$JtaO`VnCY_qRaDt;0|F!7Oh7O70Pvbd$8wirLID;(PgukRqA%G5@w&Rp(}DJ z7cU0Mf=3}>&t#OMQr}1xHgmBpe*;O^+|&^aBgx}Y>d>{iq! zhhD1L@fHaG;X#f`xCVnt~b#F~WJ zJ}~0=SA%o&a#I)32zoVX`Rlbamx}`bICZv{sFwd%$!tOjj#r#}3Z1P?~DVYi1YK7YFMzd&7!D9pllMG>YBJ$r}|` z&U0RrA)jnW(Mc5W^%?`w-nJMccq1ft_2)>ABaMExnBe)e?mxy51tgy^q^T+>x+>dwG0Az_1KBuY=i zc+QH6t5b*`N6^ULCydx^3X8DHooB3^Dmciiam+oM5f_U?9KaH9+1q zyc4{MC3l$SG(CuUSm}DWOYjTWDw$7A)Zvd&B#gCW>KC5T0fdszt93We^!O;0seoyo zaA#d~S2a)y$og=4#8vxYZ{r_PraM@`aQW;m9Ge=|0>GKcLl zlua=%rt_#rBOziRsfIckU-2`9q08;==1E8zbJiV}O0tJz7tLLMP_k{cA&4{^<@iOX zN!QOsWs|d8JWl#?e6SBPLd8~J2W5`oCpn#BXH@US!v>OmQAc>ACzMzUn!tfl_q;{l zMHBFjnHQJN9BB#3T)Uo2jC`&Yk8ndV!Mac)7B3(a5K7^Lt*Y8D`}cpz5eroTT1l zfYi@Lh15w+A-^KNJpt+KXoz47%PbJ8Xtc{qVlPymV5xwz^KWi)K~p7Ro(~&NDfR2^ zGe{G1FE@cC_x}Mnj;N9&MsM5a<5slMT(a@0zy@HAGR+DcrCXSJoe)Q(qZ2Y3RAqVh zmE@zM@$*XH+${tCoLxD5VZM%e6}OZApVys13+JB$v=8bjD7W zMr7Y3OPTP<4bn+<(a4=uD=YD>h&ggQ0}*?DHs{lzjl-5(du#kWeH7>Xm~$|1C#p#T zsx-#82U6g+qOL3pMF%0ZG%Z{qrwa@#aJrq7+PE#1OoOdMkw)3l`AV$ha60F<8Pc>d z;s7Se@>-l5=pjiqx@9(^#R>d8um8xo9yU^3OtLeT+uT@IxqcScDkHnpH^R0_qS!Xr zTyX}jQghc5%Xy|5ifR9DrC?fd4oWtiCm6ChN;nM`*fcm+&r(~gLlsSS{-p^wg=+-2 z^PCsy4||~&Lw>1l()L0;7&pgs+D1&i3bK*Hmzo&ZwJtjVP?NHRYoI7QpX)~Og|IEK zTi;(+GEPdb_7Y(S3^qOy_qM;@cCY|7DTL5a>d#=! z`ESXabi{Q2#7Dka$Ftt@DUm6vX1<1qR^jg%YbI>0*pG`r0Ix4!Ye^v2@lUy~YP2*P zOi^`w3B{7ckElKJtMWwc+L{L);$)}OfM2w#9}D#-As>VFWM^m{;*IV63^s${P&u6W zR1^33BjN=6YopHahvOjR933YYgH)(7uL4$_N&pn3E5_dl9%}nYbi##lV5(k}&#^>v z%>evSp*y@2eZ=s;6sccrn`@>espLdzlzEldv-xA@oI{jV0Tn%QFI=HIaP9e82jGk- z0h|qFZgv|Jd4wGv5cRpm(CYV&&T#u!D)llvs0zcO7Ni^a8egztle{Z-4uEHeQ&Sl0 zip9D#(kJIDVoSkD@hg#O_t;?NJ|RtH40_HK15Q7)aw-Stdp1YE#D-Nwb@XRz3ox>B zYk_&G9Ky%oq7`S#q%G;N_kDV6`J;p-?_Y7tEGd!>B?*5{>bh%fNNDydB@2hjW-p;^ zclO8@CK@+AKH2~a22eK}5VRjG#gSh}-F(-OSOxnIS2@%!Ja)<;wiG!5$K}XSqW(a+ z9}!}st`U+lOGXihxE^(HS*d~bdzkY6Fp#=h;NX~Wvq<#R!Ay}A${Oswv0Dmld|q1n zf*7K+7}pY4;QN8f=3?DYo?9myBw)D?Ayo&{2uo=oAA)i8jSC^1^9fpWARd=neP%l( zL|xj0fpe7%eU=b~mJLCI)Tl7POf7)N5rjT3)^@6F^?YkaPszPL^Ry9*=LszPcMJ!Z zivksYw2FohWqX-Kk|Q}{(bvd{*mls8DzcE zeJ9^ormoA_%=%` zHI3_3Hmsk12)9*r;*}+l|FL5YbQ1^v*V}3f(*8flNC;)bdOWf=zT&C8d0U_)*MjSa z)S#eS#9Tvy3@1c#20p>Wo4Py!+6V|#f z(XobNfV3Wy?Y@mrk}QPBAzpD9v9ITcA}&Xg&5=Rt?6;-MEYoi!=86|ST+&LO!J@MT zL|B{}XbbEq97WpV;@YSsB@ha-S$#Ie&>4jyJLU1tM%2hnqK8a|s!-yWQf0v5BL(w- zm6D$djqLy$-CBe1sQdqs$p&BzHUoa}Y@;~{mq08}ZF2vJf9-Bjb~^2+qXZ2dhU~rm zX}3J|??!dsAN|Wrf!U+9!R&LG8=2OO`(HQNwVTFhroQB|pB%81nO@Wh!(LUL>fi7y zDxi`;NX|J0gvO9D#Bd%|t$%~0d^%14h-v>5dq;zmDi?jrLCpnSs>`Ap;>rVgkuhkY zY2pfLEdstZ6E1V5ooeQ;{HRYm>9S~ka`3T60)cftVW>U+}kY4*}2nyJ{PJs;vG=w*S@fpF07p~0l~yG--5ab zg>0ivLHx1!6mvhP{7>_PKUqwjYnv21184RX*Sr$uJb`jbSxkH2Rf_B3vP^3tj7(c2 zHkR9$q9ZF$S?w5WiD7hd9dVsyjvlM9r48x?Hm9-5;@XFyZ3ZGx1g0&CVoUTQu=wq} zFe7U)np4}5|KFa668(*c4d#~zOkt9!ec@N#T+xi^7t`9?P`mh^vnf*Lq`CdE-xvM#`gJ? z_Cp+AMG7&+SpaftXV~Uy*KWiyB?=x3VU)~|;j}awe`-qZX03}v6?D@|eP~v*j!?+L zf9(H2fTZ01#v7~ASlv)`ka~zhxRrFGCZmIuNwEHSjRE`?B3Jj4i!0mum7k1Q;l~}2 zuNVa@R*;PL1*8MeiaZ0ftu7w^A_!M3A}TfGh53wMCy<^g^dAbb=}(VcnEgf#h3jhz zqu&85OGWD+I>03FS&6Vwr{BuKl?!^DW@2(>dvlk}&p;Ni5=xOh%dOxd-n*B8(#!=I z*iuc=0yD^&Kx+BS2-#zTfvH}dfTbM59pi`gCTU|-_@G>@rWF+O7$pCn@#A{i6~6j z0|J&sm=Lv}C(b5A4G4D@&ai!<@%Mps%V`Gr@kVZq9mk9PM`(Uv6d{rN#@Jak%L_PN{edOIzJB(pFJm7$lgkRiPaMC zFYV3eyxt#1L`=2g{X#x3d~WW}r}FS|4WKd9#~ecs=u)4{1-TTNZ)!J|Q#eTc9} zyN^qmaKvm~7qnuLeSzehYR(dRZJ~+G<8U=o+Db?Q74%^$h!~UOGZk;o>0>z!&a*oN zNO51LrQ{v4)CuKxP=aN4-nWMB_hPgqWSPtZ3JNN+)kOMk0E)j-rhb$8*(j_IxChNg z+PKNA($NO;i2m)o!>YP6Z!!pRPj$?Gnozj#`=uyDArjvgQZH190m6KZwrVacrcxPP zZYvP@Cta2=`k^KOjDg$R^r)!kV~)=? z8oILM+%Q+Hu{r7&3#Yk5GRmo}?#)wL&SHqGx+}Mkmy1wvtB5(rSMl_5BdBIP8_jIk zBpj#347;!cq+mk|5S4Y75^IS!f^APx;f&8IAkX#I1;PEl-0%4tlTe^pBD^TrbYry@ zBgq%uYuGx3tsb$;dTFnyYGVT~E#pD?8Q|EtGq1nu#1a(L0R_cjX>K!e{#x@R7j~5| z2st_2iWzNH&%qajj%G>v#i!+%4hWB7UQOq_{x%Bb1<{mQs0b=N=nb`g)9Lugbe!x(xrQ6RJ^wR<_B({#cg5}P0 z-D`mHafN^bPUGMz(&7O<9z+I|`zv=O9(lSI#J)~AQ;z<~iYHXHt!lD#iX<~*`h41T z4pM~?x-iml>Bdbg{u3U1l#Md1DNwV6M9OSlgr$Rz%Y9V5v{9QzA3U?)=lcJHNDwKL zHV1NmI0Ow$-oFad@_43Q1EA4@>?WICP%sYiW|2F%s1~Jk89-X8zf^W}?LbaC)(KcR~1+nNQ{BQ&SHIu?g=SaSIqoPMG5h*dBOV94IBQ){a!4^V(! z9C%(C|Fp@5SzLvRD0wbuZ=bC#!|In0pEUeJG*}{K^ukusZy!}2jcEgu#Ug;Wv{!gw zEy~P+73r&Ve=43&@$DdoTyy_(mEhf}`8WS@SEd6!6k)``GwhIaN3+d8|2=X9i91VP z;9DNjWiCByhxYbqRy@TJ*2!}08v{#>SpRU9ps8Yqv-CpD<0jmH2ShorAihgAs8=>> zpM<}VyC%3WmBI@giR=Qyl2gL})Ep`S#D^vA-Vu*nF=k69Dirt35x(^;C+01f>aH3E zEfd;xx&Jme2BTHiG0FZQ#2S-xi|BKTA^YDH0XDEhQNln)UFpd`BpLAYpKxNB)ZyX| z%bzL=GemPomhDR+{18eHOuM`!TGyoKhX+OJZ7R&(!l<)`@Olqg-9zzl@6=1^ayB!N zg?SJ25so1h`)nwP7zxd60{AiF=s~E6QOIfeV8O@@L0C(WmHjOFB$v1_4!4_d6T;3Ku0O3u(YExgK3NYUGUz7kj+pmkhE0 z2Evu2j!dO5+Gt$n-F^9Lp)Ro_@bpT44OuDiI-GTYpG8ciE8Amp$-+2me@{Sst{+0Z ze2}89&i`zmQ@S)tdw&g?{-$!MeQ;<5nb5iNQK*qu-yEfO0zl%xg#P{35Ntz(Hy?3E z`;7Q`p=F5M%-7cWls3xIT(F*Jgejy&VPuC?>eCq0izI94@u~ap!x|EO1--0kFtrYC z{IdhMD&}JAc0{~J>9zjHP^;rv7S>9k-foe1G*zbiOV+`8<2H}aj7H4V`}?sF+wjZp z-+^<$VbX}Tq`L33{=iG$SQL4g`v_6>6Q|)@(kNm{z zqpSmhAc}v9lt(($z&s*|e~eyr-Lekm#K{pB4k&Mow|l-bGTzNQjXg}!=So5Gt1+$r z7fy9v&>_1MmwIYG>V9@XfQKAlNQme59Hn5wKAr9lBRH&$d~*sl!2d8?kt%M(_)+Dz zZZIkwiqEwrm~29lEI9_Fzy~UGmUY1`H-6gJ>cnYuj)SEYjA#AGHEQmtZHriH2#@>g zrs4rUeR9x?7OF~S2gAeWGLxJ3j9HsJlqH~9p9--dD~pIPoR$~!ip`=uaxuodEey#F zuE2vu53NR{9`NAi)F#ET_$;cPy)&3gPe=WW(>JWMQhc)!CB5m`R=~i1ODeo2!Wgs^ zF`Y7}Q2I8WM)>&{q7^4}|9R~g3w^Id!S2NF*d@&{m6X9vsBMjX3x?TsAoX|;xK z`p1wr?*PON8R00|LklDYuc>cvPDU~J&;a#FaEOOliOIMZ+A44@ZPa$e3mPy$LBIl2 zRseMko81I!R{U7#H9>zA#CSK*kl?%?w?@E?smVT&#aI?$0WX;Ti6{0R=1RdU^g!KS zAZ6azs~QUbQlF>VbAb`buYXVSU#u zA-gD8=lGF}%qr(Kdx0j6vo+9H9KghdN{xFebH)XDqu~b7F;nOQtjiPX-0g|DqZaKt z_jh*k1nxMVX6y_N4gn&>P<#b}*Z2-9rOQHH@X`OIInnp0$iOKHqW)%mQ^(BN>^GMN z>CK#{kWeLNkaAmJ`h2)C2l6H(R{MnIl)&ZQ z(r%BECPz%?sj6v$1=n!-#>~&RAgJdTAg&)vcW$Cs`fU#rND@}sb>WxzdT@pXp>X$6 zHQul@8OP-!y3N)|VcFG5aqMnh^3LjFsbB$0Y13V$EVhdzb64${cj46#>WDM#oXiW2 z=Rd^<>I!<`wk}SkHt;auPI^qSi{iKexe^}|vuc_2P@N1LBPuV4;bDk-cLGf(jl!iF5=JZ?jLA z-aOoXX)3BXnnw`yFEF})iSmkgQOawGirP}9F!}ZEsW{QM_rLC63TPz#&9CfiyD18Hd!3W7Y)D}uV9P4N)2#H>1Tq&@Z z@Qlar;#|&59l8)*!|cDms4AYiC33gyV}7%S4&kK1lF5F~0o@tkeRmTqFnl8V`7{BfK<^OjoV$}2#4oW!j<|PMbMRw?x+3(N2A&GXg z>(!-5Aef4#G|LIz6nCbrCAUx32*&jB=RLI~!86gDbw6u1_Ia-x%nC8nH7WjwIF}If zhleJuY26LRsLZAlT+NFZ#DYCFhWfFcv5_EZZAJ=r$CF|vGvEoBfDVR#MN8vMFEf_% zTvhoVX|kFR&1If0c4}&IA<@S9M()^JHcoOC0$j|dZW!tRE~;3lq40mutsA_FvOs?h zE-p@{sGCcPCq?fhD%|*a$n&m~@Oj=XzS<-8ep?;WmcJx|XY=T+rdkz;kTNLfvN)f- zFot)Fg~2HJUgku`bER*zABUf6+Yi@dn4Pxm<-;xN4Jl?2eDEv=P#mvL6C2H&@3HP) z#h=$n3s~T7x;`HhGQ>4=<=-`41JT@I$CL~9i&cI+nzI2@UlxOOFj2C%)0gYlgHtzH<&)>tp_R>AiyYlM_vb%V&ZPpNXM)Cp`whT z3{}y^Foj1)q->?y4ltN=Cjevxgo1)CwR!ID*(D&c;Wd~_deY@9s2+z*{z3qEq3(j@ zfLLUhz|cbjJv1m)^VdFcP`xMfJe(0cis5t1;X*n6LJ7?&60Q+D&=keNEI%xh2{(ya z)t$hAs+QMq*^)vzXLs%vBv?k=g81#{-Hhiq_aZEtw#po9T|vG~IW*J4#ZQ%3VF6k1 zX|8A^XE!<2&eEz%~VOlP{NBS*NDVy@YFS=kz=vOXJa1{MH+W5 z)hic3neDbT`q{+nR15(RHXb~NPjyvhhN!VL0%I4+%n{&@#bf&xVMV<%o6AisVE!p!+L-U#@Ud}2idm?l9!%qe_GSgL+Z z+qS*S8}J(}803mBv;WWs%DH?JL2pzCkl3bCn+J2SMwiy!4OXa&f*t#><1U2LP%}^S zEo`9lqrN+=iBc8A}l&{DPUg})Pwg!;r1}D$( z9Jg?)YR0`BC|xu6x2#vIQp&*=|9a2&z+@}dC6;RtXMM2nMf-R=G)4!fd&=96rHR`H zqopK}cF3;n*cv@TXgwn|QsNZ7RU0`>Ip|+U_bWPZ7bCd0qNazqGpd`iVR*OdF0>$02-WeAb&X^qyZUk3@YvnXX)GMbxkVKG|*uq{ri$%99i4v!*5_xyw3G-h$wxOX4Lnlf1&grFw-U% z2bp7RcV)ua2Xrny@OrQ)T|penJh`;wJXPlG#5SfqOH^jB8*E;~_QeOj3I6QGP@k@T zDq({vsTdqU9UD#U#aP)j2$Y^hI(+E2>PKgydU~*~pG->VQCj;nEOLiZNOGwE|Nr>> z!1<8NJmW7%#3{BW1py9rE}?o~ik5pkG?2Kfy!;g7jU4(Z&S5Y|Hbty;#5M*RFhqxS|0A2Zx&T`Ox>Wwk_w#^x^&Pv?Y%xw`_9tJ7_7L5v~T zk5yqab0Q8?_JtKHFC`8EX(LisfuAGR^%SzCAt@x?vNktsa){aKklP}QSik@P0^?!O z01yBtA~XNnyo^XXGV|rAuEn|{yU*X-WY~p&_AIAjL`IMS%m7vv8i_mk5t_&UCIq^G z&SK{le2T}yJ1f52Cd9R%iIg5SK0L~JZ~m0+35lJJ1m_rwQ=^01=Ekbyoy9-kxZFjl zeb}wC1dl%&Z`o>Dk08rAR`akU_xBR>6s20K{VYMGR_CxAvF`U=lHS#S&?OeLYBp|s z{;-Hn`RPk;O09@FFUUo;kef6kLc5Ko8Ak|^J zftN#hU#8;MbQaP~cKs`l7Og%;Xud{%fnYSWw`#~{`R~DR3A(slw7EPhFWO}H{c!V) zU%S^ZKIk4TZR`5(@@r<8rfP&hGK0uQ5j61vFx%FCS`RQ%f`Gt*`}^5pmnO_EYHkv3 zI|bF8w~WPo5e3gF$8w23@RaH5?bUo(dqJ{K$@nS`)AJ5>*U1Ff@WxSig{SpG|C-(F z{}~b^Q}<;NDk;>pOg;DsZd0~+cs#z?rZ;KIWzb-USa<>35@*L%MHt-!CK!QTM0PZb zheydC^Ox?f z*>n}#NHHSFJ8uB+p{fHtW{~j#|icQn= zE+SF$)!*zZ+%|Bfxq~`B9hOm1}0#;-lqhD9v0CHJIzH77hIdsYz;)!!pfTa0AgbOVodVOaZfo zpx*d1^lWB;{+^Hat_?Xe*e!TA4Wq4^jWXm^;AlcWOkb>ZmEtlNShw7IzEt?(N<=(5 z6tB&_qz>tfN-5-gDO3fLY1cfGDnMd0fnOE{s2*)x#;_EGwLI(9QkpRCc|ntr=;#pb zGhOI`n|NJ#SLZ7X{4BOFN>z!Y+dY4EdsV;y00H)4&;T$1XCf5;OE7|1M}jMn<|e7y zrK7CzNV003=Dr%rLGI%MoUS9R4#s;+MzB)sn=Gz;c0HKgO}wIVqd2XWN%gn%OKq*H z%i7*B*V!9{L7%}&O~i9|qS5+2+-*zkLHS$#@OdfUZR_8hPF%2$*&_KB!i$ROVnnHz z5gO`s+E`*2Iv#zT@`Om@59Lj;5Hga|y+5tb7ksX!Eke)s@WQzvaezZpd^bY!2%~%r zEpx}yiylb00E{%sx#1vNcHagcZ@@9J;gMsTG(o=3Es_bhE^Qnh5kc+&wN$muQKFUX zHz!i$pi>>IH1)?+|CGR7r|MV-_U!md2|VGsQpc;_YQSb*ZeX|| zQ~1w%Fl^`2I&mffMe!hK`uGR6ecFiBOYQ*~Xu&bYE^zO9EhSJrB(r`=WY)9ml$^a{ zMZimnSN9`oE23LqjkP^*J*6AnLgckmn%Kv2Ec+$^JD-jMmJAolB+g(k9%rAaIiO>U zEi+7e1ynd-TD6OI-~a#t?_tmYKmdm#6#rwzlsRp%iVKdIFiobshHxkI!9^%%Dy;(F9ECN=#2!M$eoPs>3pOW%1+`U@~UyK`(hZv=9438hlp;_ba^s zLTJO71_jHAe#k54C>P#zg%e?3@L`!*-kg0@YECZ^G@yVX%K37hFHTS`_1P`AkDj0q zTDPUjK0hB%Lyt4P2XjoadjJXJ;xVDuN1Z+^q0H?Rd6uLwz-@e0zJ=2({^aK)%99;L zNnsaW0}D?8HQe4AOTH&ap4=n|r}SB=`)WUZC1=td zapwiUpB}?!y#4QO)b$QDyB1$a5n{SG6*cOiOF%qpXVqVq%-_yFa}qu8a}&ys2cSD; zt7<9RBDWRi%2MW>m%X;DEYaWwn*680gp{jj`Nk8QfPA=Q0}F&*HbZ-eHnagWYFt?V9OsHroWaRYER8SjDcUgD&eu-xHD>@Jay_D2 zp&KDmmTYdoxh;(gznuOF3@}J3UH9Hj$`?EU4Bmmu&Os2lUj2_T8glK4jwIADVsMd7KJZ{G*mK*h6O!}vZol4f_QY;szDuE8oR2d= zLsAOg{pb(X7;$i53hFl@!5JtbgMM?_5VZm08(#o;B16w-!f+Av3uaJ6%3TmZNC}gf z@1qlQG07|27!MB=RyCCoJQp&DR2l!#e*)&rk}pt^`0J0ksOUuYru2${wOEUmSN}?f z*@hDGbeWN9@GZR!zt{EJp9(IutIRF3M4UATEl!D5MZz0Y96k6CU}P+qR8x#6q{Tti z;-$<=-IIPNmxfG^L1Zxcdn1-MGCTZ}W}y|MzyJUN{$bDnU;xJ=692V=zQtPi>aH?@ z2Aku5f|VkAA0Hw50jPY6$BT{xx3BB!dQkfrSVY#^ae@Z~RR35{LVFC;SSL6Pn7%Bp1yfXx> z>v+_ddHhE)z3nP<>R8h%%?+n06sSRxVV~Lov4`wf#Aagg!OIq79y^jH@17=PRO~^P zK7F?gmbS+!8Qz-QY+3xrhm>!IiW^GSXT{`u zU7r6z*SW4u%~e~gv}+)%xz*WOY`UVBxht0RPXA+fpM2d=8Ch3~R@ZZt^$<6lsXU8j z91-`dQ<1JrXgQ!d0LZdQujhb0&}M`&@)IoNg#* zu2BW)+1>TmtLMGMYyS0yq5xr>!>6;7qrw^>-4Q$;!Ix^OlGn{(aGNXG*4?vTvkR%} z+WNYpvZhPm=mW)SqJ##0N~VNi8=D2cHsNQ7iwmb!(@Kbid&kNZ(PK(i86@B~SDaoN zI$69NBWfFR?HgxLLPX;9k*iNb?g2&s00Hh{&;W1%=OPyWfhQLF0*umQppaNmh=$Rr zR`oIH4|``OjF&rTxD!XLt#Tq7xHVZfAKj%dVegYb|I$e-;m@!yVucXbGrJ(Y)GJ0- z6LL8?FgNWJvsGhzVrKQ+#xE_CMzficKBq1SazZ7fx^<69HwHp(5}p8yq9DUj*hx{USo?ztbK$pDjy?2`}t?45OO0U z?rNS`P?iUWv0dY>h3@|Brb#*IB0*WYuQf)eor4k?ao_GHZM9#F@jLB$ZW1xOvUm9> zF7)t0pV|~)OJYZB3dyOXz+yFmNFV+{IEK}YLr^oW6F7V8+qhSSnEU5+hWrf3fgJd& zG}kE>j5P;`Wl1a?mxzUdL>D{0LMwWtIhEPz_b5$*WEplSRO1}?orQbzw$S-0{UfdA zAOHXZQDM*kfB^?0JO8ba8l$J2uh`uD>17S^dzLH!e4D=XelAu<6c(6RB5Wg1aq)YS6oh>422bLnNG6wlpt6^k$2D5i~wT zAvPHkiB*w^W8(njV{K+;q10i)2K(&^bosYGNZe`d4qygukFPwg3R@HS#MU4N$Sc_D zb00SfJa8`{?KBT4OlQYC;baFXq7n_|LN8`+%nqu1OZ#N}OO|*7naq>)e-&Jnh)P&? z_2ZxX!>D~mIAN?In-8j4!K5{G$!R0Zs8?2evetLgb1)ArH}iHxAm}wl(W%vtC#Q7~ zMo=?l{tN7YdCFp+lBtayhC?e`c!QFB@MZT40xk-kDNx1$Sa*}smHvffYNO!QxSYe#5u-LAz#UKW|U6Y^jSe=%zr>KBiB34ZahWJNcRv$E2Dk1Rpj4^-XJIHTc&+->?Pd7V$S_9eZ{m*%4WoP4<7EE)*!Qc8KTiHLWO=_;h0`Fna0FVJEA~XNny<8>sfY^U~(^=21?k-?a z1Oxk=Oz)lW7v%Ds{;rgUs&#|sI!}Ga#*n|#jj_R>@|q6{2v^6C)GVAFs?`{}9&=vK zbh4okBO&%7?e>%$$@YJi9;?6PR1?Ji;=oO9tE*7rn%eZzfI~IjC1^MO)83o9c}z-V zwvd!2b+NvMyXjKfGE=*5<1oD{4wMPfesP}*mE7S4&y<~dRt<_nvSm$Wu%mBw{jy$n zP+%|3e%Tp>o(NkFmKptX1R{Q7E20fYUdOTbz{qNmbepL@pWJs~zUMi~+lD@OvShaa z^*cX6%QrY6iH+OGn~3Gf=o!rskH0=0_9L!_zQ*wgkbOTE}s7Swk zukFQ)_zqlx9Z_>rU3J1t1gOw3ZwAG4h#vSH+bw-7UOT7=U{K2lXQ6Y$0Yt3|+FhF7 z4I8pU2_waY>jN`$#ZLl1MMlJSTQ>rYsK=z`%aqfZI!+J zRZDh|mC-Tzig4|%I*sHNW^(}_5X3}i+uXc?mjnRoiGBc{n4k!8ry2|Brx<9UxV3hp z;-a7x4}Rvb$_s2d@wH`|gjdo6LM$4_yPWD@e{9qp)Y%K=5p!FFa^#8sc}Fzi&4qGU z?W*iP?!9{Qlx^sG;Mo?yOK$6}et+cI8Ufmw$x zp9T#&0o}KvZx16W-_T2E*xSBZ6$RWx>ZTz?1tR25pJj!{>oU!Js;4*d* zZAqLHgcLyWL-;bmn>c=3B5UuBUMZj2+J8WdAiA?E%Bo zT9~DG4Bz#_P_(Y)+&DYJ^Wg%4IX1v!G$wJ4q#e zMQy~_`r8&0aH5uT&MTx%a?Kckfe#dJ0G}n%DRlRd?M`|Y1lPsa%G4rM5$4j|uDiGH znXc-bD|Zn(`Qyq@0gi`OnWe)<#M(T7%KMSrYbwStp*wcZ2j#?=IsYgJXNG=vh1E zdDV*ozWas=d+L!@!JZc)JbO{jC)A#|Kw9xX-F_D93rzG94fbVDV>g40-WZC|qgHP# z;C2iE1Hz~EN;7Awz~-Q7-l|6#uv>@86&2Ez% zg9|q$=~PIRQb9tU2*8eNqFf~!iWAvGdYg|??E2i?7Q)L<3zTGS>T5MFLhyYMy#+KM ztZEU8FXnABAZ&-2(w1oK(BH>~fWvV4tyiAbvfM`wg3}lx=hY=4ZUX77!J-5=fYaDw zD7T^~PE6Z+W2fRm`tJCDb;VPy{b(Ej12lO~!?|oqUM%nc)g?%8QCENf00Vtt&;YOj zXCf>AFd=;!XP}#FODMS>sQ!R&p<)e~BRBhf>%%z9>}7}*o>bS*>SR1#i|@LaR$ths z>WpX6v8=Of$;h_TVr&$#ILa5eg+cz<9<%4_?yJ$d41kuvipZVV>zm8!!&^~7bdEwjJjZo7F6clqT|UYs8i-A^~V<) zES|qcR#{>AM;blBnR0LNS+;o`REU3R^+UdeGimjKHoGPX2)NS9GAT7ipvG?t4yn6L zWvMAbT>*RaRm!D|i(_O8uPr2Ic)xqlA1wht0?3wnKT^G90dZ1CX9=1hxBMSXcj9Mi zv<7=2fIxAo_+P&3pKd~uCSwVv>b~9WJcDgG@HlnLpPNtbL1yFFUBQvgUb)}!n)#f# zn?%(I`6pf-fulPhY&_1#jn; zVFMxdgIy?zW*#qG@~2RqJ-@H4pEzZ%wDj5KN0B>6K%4oo9Ff)Ckv<33;MOm@!LXbA zYOACafDF7xU3!3LJQO~Mb)FgCi3~dNZaG7gD~;B6xkH%9%;9wod<*y{(2)?KW`S1N z55@2+w0B|4w?V%_VL072w?NW#cD+96=&S!a?}yg0$0Yw(tnzgpZgqBPpQj?VVqa!O zOjD&TiwXI*r0Zwg@=l#|-};dp3ac^g@fg~5s`%8<0_Rz<+ypPwyU36)tI{45vU)-y zo;l+FrKe&j9bVBxt6_M;fZdN{;5S)zaTuSvu47@qo<{DGz%sBFKhf3O@>>=w5Gd(4 zfaCT~cZW?azw#wTjBtvVqC9s9kItFAgTwx+S4>NUNz$Tzu-R2TNqw`77txL9ka0Fz zA^&(StS+|bsW-&#l!LyD}EUO>4>T@6$x`>_6m*cVQ zLzN$Y!uv)%D#7VWZUZqZ8gtnA0g-h%k51Gn+}^&2d^p2C>;cKX+I$zvv}pYt8)CI- zs~-|2eD&Ajs8eACGC*VOHqcfs;t$DHbf}B(hl#G+Ng|X5z%F$KM^<%rec)P2#NapTI{=YF4^}eah$C_zrqQ*=CSzm{*`v6% z)WICj`^%78H)8C(h}72vO^i59VJ zn=8ojqcySODi_j+kdilFaX(J|1BH%=!{co>X=-d)Yq;nU46lU!K?Bak>B+W>roY>T zO_cN~1Q}|$4&uk~wi+``f?+$v%C!^-J5H0>x4qmI?1FU6|4Y#tZXjH(+3zN_q;wYQ z#T?IJ2PoBqRTou%@Kg_*mj5~DbG+xRBN9{wGEg)2ak|mPw!yapKZ08UvZ6cJKSXmv zm+zSAG*o}O&7Xq9L;d#*cI0euFfP%cT!0<|H2rG_YEjJG7qGW8SXVj(3`kwS+ zrQ1(j?;Mi^iaM`l-&_i;9!f#TC8{>?y8(CEjxHcPwev$*JXlRou8Cjxym>X=X zMirh)@F-6!=YEgQgR`nG1WqL!yF6LBzUu?TC>;|2jS!4dTPbxE%h^H7BbenYi$1V( z2341?K8)%tqbOG-2+#I4OhDwe_BbDMvrcWBK!Py!3hL)8wI}{L2#WMOR#FJW#=bz!acP9vL7B`ZK zXt+-aZ1!qV83=BF1>lV}SpQk7b$z9d*Scj;ju{q9=t4IBB_-`%VB;=X{cIaBH8Z_%7QRU>T_qPC@@gt8)1GxJFqnWQj(28Mtkn6 z1MVasj~t=E0009MVbB230jDA>|1X^1>K7DerarT&~lB)A8K?pmX7hqv5 z1iD4dQc(%nIR_y``FBI+IB0cJP_DOtR-4Zqu2#AKkO;HRUQqW)Muj2Iq4B&_Pq?(B6wR##+7{>z54OwV-Fxmhi^TdU;H9 zcjrirjz_>&+Pv%c7a5|rL!`)t;pkSj=NBCbl7^$i0Kr|fbL=9>N#Dr;?RHH!#pE~2 zkl#L@;)l3TMAGgJ{i64nBUroSSMBEB!m+67ZFO9}yEvsmXaq-wALKz1#i!d&jln*p z%|J?WscBnWv`2&R8j_-;6zEfkgI2(hQ)UIjQJJh zZFaqN%z+cS&W*K`g^FbEou|4byNDby;GvVh!i_z*n=n$v)6qDvWCv}is1ylzw``Pz z@BZ1%_AWsa*db@RMmZE>Tz(E=)wCvM(v{C6JSYLCHht3)N@eJO8u`$_sr+G0-quA? z<}GHI;_Bl~l0R-HMj+!DIvk0LZ;nzI_rCodbX?u3f4v_(?l8dc5V5+6*k~!SE z#;t^>P{uocQQkX~G96h7qAJ`VEI1=*3)r(}5h__TU;1!Lgkz{Miu1ob&d*&6gco*x z@Q&e90FVeJAh+~VE3E@OHBgiQ00R$U&;Z~8$095LVNCg=4sK4{CH+j|2{5PhWk2Mr zqv@~mywB1;A@Gk3-bGDRBAWndw>2#ymkp2yJ^o-LAsV8R7MXP)izpmaRO;}PXbCUJ zw(hLD3{-!`^yn7mDA#LMGv2Y%)L5S%t$%OiKPt(M<4cbSOc&UTG> z6ZQ5K{;#lHRM{Zo0oCBxTz&^c4vdlP+kc*dg^HNm<7VoKvZLo?fgSs9|)X>wCnz8&;Z%Q6K3Cjxyh2mpH#mly>NQ$D5PMbhKXoXEf{l z#K61#J914e1J3FngoV43YCtpG96(>Q$o`{&rvsegQB-~pZJl0Un2{fri>yRSQ0+{q zPHB~pniSqm|3a%q!5jRAe%1^-X}S-5`tZH;4TT^u5$i9fm?bg-?CFF zBAv6+MFXNEWkUmCecA0nSKYZhwX2yWe%=Wh2wS+9O7fejSFhu(QFV7tS|$5N%vD70 zBcqtPg}^O?J^4D`MfDz1rhT$egUcL~Z2)W}ZTJGr4-XGI)IOLA$D}}s z!o?Yn@w-^u=|hR5jP907S%XpCET4L^oI-*_B~N}J`M2g$h($#UqF(dR#r95Eu@Qv%PjEF&vQrylw9YURT^~P8W1YbNqUW6a3v<-b46s`2AB^(mMXR z?hG?Vu;BDrP?IjCD*Z%I9?pwRJ7ma-pkrB1o{2sOext7oiW^OkSw1NRS#r1EPAV#Y#wpT2?k8RyO6^)hsRm(iJsxX zOkh0jx~rI`a4=0imgNo02mRC?@CgA!xsg*aH!%=d&e45wwiMl#+_a*3?nE?f-SzZ~ zNj|uiw~0t-Tm@JLT9^$P7;qT3Cb?qb2nwkoF)MXSO3@UUl42J2DxTPz%)ON8U6b;u zvYScLpGl7NTuJYF$*wvBdduXbkC4aytgZD9Yu7eRrl|!5T;Dy+W$E(5azp}ik)<(+ z-utaPmx8K8PgV1(>0kMKx2ML)So#g29uV6qi9XbmnOp7qAi7?9if{Rm9nLfw0-i`0 z(|WerHaQiR4&hC17jwsH#xo(tN-DMik7&OzNGo$UcxraGR zv>dShX(jlO1v+`saU%A9UR*;g`@A3n1rI@RS3k&Ak&}|bPg5%dkCox=RC6zR1OIll zu*8-^jbrpG+;?t%*<0AREx6fPFtHFHqiB|VA~)l8(Z~2hiw>+((%znJ@qj#RYSEvS zQvUX@s>|9SjY(WKEIw8f6lCU0lVp#vg-+=e>i?I~0M%l6GMdtuU#9-sj#0#z-y*M} zw@uf3wM2~LI60Wlv9k3+VQ=SJSejqmAEva;&m;&9jOf<`YJQ2n7P`bl>wwWb5C8xJ z4Pnp$00IXh68~G@A*~{c4o!2oJS(uSj8{`UUDGVZn&Xh$@a?Jfnrt8G6v|OxCPWix zO=v#_OxokD%G3VzCW%Zk8|9ngqj(#zVbwsBBScQFleGpQU9unL7938e+4XWoFNunw z)t_ns_IrX^OlB{5e;eD__%LW%=i%lJwx_7>+kH#tCr{=y?ivkEPT(L@Nl*Wf+P<>9OFPTr)CU%| z#aA{F*tEOSt7q^2{)7JAg=O7Nr;st4pG*4{J;TQ^RR7`#%JjgGCh(^3kz(m9DY_1q3`Z&algDDqX7+dzjT+FdHA z8G{7GSVQj_TFTms zJ1QBj&INFF=2BXmgfG1sk!CLrZJkP_oH3 zK+P0nQ4)<&BT`}-zE#D3RK_e=A2t)IbLP$J=>l3)18Tio5 zM9rL=+!4bik_T-D$8cco(ia*2?c|{sbDTs<;`gumG1Xbw!z$jSnwL01X$w(TjWFlO z)4?qq8ChUa!LkB+E~dyya0V|+(uBu7&OQ8R`>C`W1}qI#a0M!p_cdgP%r zOF@(1dbb^y31V?iFI#BAQ+?9^?!ZEt;Cx4BVP}`_pMH$)`J8M__ID0Ww(~;#K)&T8 zkKQT8Q_;km#t$B5(YpI+i?DjW!vm{i_2q8{p#0r zF@8+*7nn1K_<@CMqWWCL^@9t<>_M#JQ{1o6qwBsvdfA)TLL-ritGM>7me%KJRcy^tj*%ei| zxN?#)$;*$irQQw=FM%C4B?xJl85WJWn;078FZEcr{8*QPJknWONh0L(BYo!-!1Gjg zW9tI17gjw@Dj_v10Y8r75HigNy=bs{{}qyhgHDIvlZ1ROBDXeSHN~UA?m}?poa4U5i_BEAFlbch>^NDNZR?+={zHad(Ql z7MJ37H{aL$*8kr3*2`LRev?Tu**j-uot(XsNjaxUvY2piH6=wYJqRmmzbF%}@$rCp z85@XdXMW+Q*b$4Wt&p5ZW7d5T?H%7Dz^r;Vs08O_5$>BDrjRIwW-YK1S9rX28JQI< zEI#{O8pN*uK0K?szlOIC$1+d&Rv4+#e~R zJX&^%Gzk>+_04UvbTrTme|fPv2H>aKyHe!nqF4DO&jw|T7*}4VVLdLcDI@VAzfRSM za%%M}a_=!Wuv}jd=wUleE+bcf(S(thhG}f ziDr4Uqzrvt9>deK1H}Am8P#}4oUjf%Ri@3#$49zt_o=+P@=puJayb@v7y0LHbj7%m zl*e`Z=3k2zS2CujPHabIY+b(}nY!xcqVKbF7N_$ytj}`xL`Wa5K8?`O?k#0C^CYv? z4}xA+68+BsSHl8ajTAx(Sb{E5_CWJNOy-CG`FRPQZQ;z$!}rzu%+%6NAuiLRr2Hnb zPOe}SjK_JilnXlPwOWlTNu&}8MUfDt$37G9TkH+ zh#@8vN>j?p-0G@DFWn)(AJ7P=xCK!S^2!*6v;2N|;dZEiPbv#t_=R5KTPMPm?5z{@+x%i^umLF7o821wGwo`et+T(=RN))q2U$t{ zz1h_cq2Gxj zY!3s!yq!`WFZW(W;J{XKPym-F^C=EN2t!U`P{S<7KWto7+F1y$OT*m9`?0Z>&b1%Z zm145!g%~+f1~GV(X_e8=AgJ7K8oG*@(6AIB1)m8|Gs_~vuByRD5r%VOk?D!QR9GAy zT-Zmo&PsnC;fc&_Vx8+ffV6Slw%B4L6YjB09*duNk;U{R2pp+LPCZul8T-I2iB%gM zL2rNVz9EgG$aoZ{-VBNoxp_i#lWuN~GQN8tqm@op6eadu&{l3_PyGyTj3H;I_pgNK z2KuMG9gEurGl!2kx(5taUeeC7(+ywLT9k_;=3^q-b}@r;WGW+sx7TYwM)@AG3ju)< z@0I9f=u9K#mcCAO3WKvO4|scix3EgC;C3HZO~bzUhVlcB)}e*Rp})LBb6fMy=!wtf zWofNOw$~g| zxsZ#O6y0MOi9}Vt5i5|v&iTw(G*$ZJj$J-wuD|y+^7%$$eo(%AsfeVCug8we?d)p_ z9B19#d;eMMCWN{-Srauh@v5lkUVz6A7CYm(|GNLI`WidLm7Eo;tlE~t`-_|KBg;{R z0#p*`w18>+0KxamB{u5kj`aJT+ngi%_ti?=4v3TJ${ofSiu>iJv0Fx z6FEWkHpRtYa6k$<2%&am9~r9U!rZO2YWN0{&!;BG6tfBzIenq2M?Lb)23%0~QBo5| zjX%bqplCpzGa6^PoonUmm(H7mN^RBRSBUrBNBl{PFjH`n$Y!s`QawL0<|J7m7Z8+` z7zWY6f3E&c((Bhf7vrs!UQ`!aq4d2)8QQ>`wYE*5-vA#p5-oQSfd0<%L6&XrdZ0tL zL00`7-*rs7Ij|e<19p`ux{BHO_zvUmN7QfjwXKM**gI;p7QrqbOtO;_oEFaD z*O%RC`)%V%pFV{o#ydb(Y%xdiuq_%4 z2^BoVKG!f|bSzkRaI=NJH|Tsth$v!aD0qh2amEGtlbWL}M~uku!Nm|A`gI6@ynej~ z`{23aie~%dT2u(yW*4cZ$id@bR?BqI)l!Ib51N zEw;z=H#k1M8Pm~C3MkRQcA1r?tkgBtd?jM;P8kXh5ljN84fJcHZMr*}aZM)KoObqk zwWU-1RNAq)xr0y+i{X#qeN{aZB3LNy<`&4-+ddQv#0Zw%jea-~I8IzQWC(-|`y%^8 zs7ycd;+_(?iz(-Zj`u}Qir*!ILpETU(bPPk#Hn#3Natb|2*F1^AXkkG}2Zbq)9P{IDLgDvd@n44#g4)uk-xJ z5w>Ll9_Zz+5BDf-#Jf=8xDBTO9iqaDX4H>emt3_S>lFplC|D!fauQ2`yF zdro&0mG+J(wHpax5xyc;G>5(Xr$n{D4l$m4cxLRGXwQPJPqXf~wFc_@m`oLsORj~I znY6rO%@Cq|m0Zjrq;P#FFTmNJ0A~|{2qQ;(RWy`xg71kTOC5(5K6)`ti@awBxv(p* z&4a&X>v?IfLJ6v(mZy%`eAik^eKzZ*i( zlwhG{Xhitir504@Vb%%}H&l1DS%)QLY)e^Uf1q{g0l6iTFf;Xucf_d)j^hAb%&fm} z)rWa15b>Cp_E`Acz+rq>&W}aAyxo$UK1&dpR_#sK-VFE$p6)d2FGTG(5R@JMJY%=@ zGM=LNU(ND4gT;nY3fKSa8d^0wia8ZnK3TL7mqt+y|9%WpXDbON9B2CE){JQBf3PChQ$p_Q*j~P|z$k2J zrp0MO&+ogh(xIA40LjOl!Fir9)KLt(5{Uq#AP7R=BB0spt-aR7u#q%ecKZEcf(oV% z6$@4q(P1tS##>q^F5R&4#7#_8LWxP=^c-VhF+zj=dw_(}ZpqP>%=b2vT}gd-=jO$) zw<*&TO1jd{O?PdM`(%7FMxuRmtKc3~Vzh_f?_PS;8s71Jz6rQpc+o9O=Fr=N$(o|o zP6#eMinDhpP7#1Xf|BeqZejq3`a?g-q^pt-Ec9adm08sk@3-c@kxgtpcJ>jYv)A2Y zG{$ok?vIV=Q3zL~0^{S$pM~@?r14{BT;cKv9aBp29udKAy~%DV8NyXIz5?L$yBd$UXEsO-QP1&blZpl3O3pPLggm zwXx>G(3=TsYuC+gKN;hmqC%woy-)TL|MWa*bD_6r38N9t-DD{>CoEVOM{*Ej@uoZr z$4CO*=oi{FLg1G@a=CCt{Fl)^$4?y`PDhjxV9DD{0o?L6Ps1DawJ&=`9Ic3VU!1=j zAvtgm;dP`pr(S;kep5d1ZM;2vu$yidZ|BGNjRMI!*Dw9MU%)wy*RrcPbnYx|SyZVU zYm_EvPImbQ5{2M6>Wlm{IFv{?urPIuV6IxO5*-ij#a#8_YWE&BKPM!1Qr42tKQSCv zG1P_w&*vfB0smKmC<11o4%ung&%nNRb{kXh$gagxveJ*2E#GwvbK#Ha`wwo#GGM63 zr0T^QdEvQ)G>_*b4m!z#jP8+DmVWA(v+{cMBu^Wh{g^W?uES8S76q4SO@%HQf*N6I z8HVdEURz3#Hi2*!C$f|27|VQrYu&9JU6aUffR{*H%Mor%R+^1Z5;B5&QWl$@S`ODX z({ySqXKBp0mRfAb2VY538)PKNbH70Er0TVIR|k>N;L@MIlg&jS=X$8oP;(_ zWqo?WyW?*h74tyrV7|xrhwlbPETY~Ol6R-0@0HxIZ>xKDpEVGQ+9(FD44Qf51GoKz zP2Q0WhvW%X_!{My7*U@An?&89I@Mi;H_Hqg)JAZtD5XxwD%adDIn^f4bjOBfWfW9p zoZ>A?L2rCPJ6De=LQa2N46OW}(hlETn7n_rmU^fGPWz{k`Lk{;rRx)!DBEIJP5~Vv zmJDMP%DAl}Q~g5p=Hi(W!4>(0>XW_j0HWdB7z{ewg1)(k-*L$BtzjL5;)e=i#9`ql z3-;r)>6E8lK5YlyyoeUnamv93l1aZMyienN7WSI9&b}JggzS`J`qAw9x@n9ip676a zD!KPblbE2_(Z1W+(b^ z%<-(^o%&goek;Z)N|b=*0W0mnjUe9kTG&Gm3ehan1^k-ZC_62`V-3?C62u>*96t))6p)}o zn;24L{qZ_c%Dad10slHm_G^P2f=Y=3d29v)%X;EvJG=>mA5Gid@62K`?2P*fB-K-b zYey5#Z+qpJ$bQfo-)(8;4Qb`%1VK7PA0=1nSz&{*4B3%b2pFTEUXKbt-D}e2JXH>1 zjE%EZ&uNPc7S1;sL8hv(VX4;OE^i+eI5OW!l+aWTM_X@59HbuQ2oUohk$5a!%;6H$ zRP`k~O2MXP@h_f0@v7)}A0Fw&OPG9xMQ;z$b2(u4dd|#^4eEEg-awU5BiWjQvHbTvS4B+qE29LI9ofAxK>w@`*v(r%FD;cmv!cI)c}b~co3huNN#WRFWY+O%;h z)wbs^&+0+P^4B#wCN*z+V%!ePfi|LW<2%rZPOns3m0A_38AAzz2x#Ri^6MwjCTh}a| zsJ4>(l%MHxBk`2FuI^0ek0;s3M!ka3LiZ2)sE6~N*hA>Lm6 zEYNQubLV$oP7Hx|!#>*b=61T=Ak;|xV9z0XD63w^_$|i(7iN}9n1LXq5b&diJ6K9u zu6J35F^xki$J%VvRVmp00fp4v{)jxsjTLcAK!$ujJT*}!Two9-(bZICXCPIK+&;rN znfO@|^Fz*=&6(@uK|{vi27B>oXrTtJbnlf|!83YH3HgHR5e00R4znnqmJGIx>}1G& zs6F2nHbE^)u;DlOdivLf$IfNccvCG;q`iqeaebKsC5vV(8D#Smd*-DY!5*>TC+mfwQY^m?Vo+ioaQBRJ8o!G1o6ReFNV>s2I*Di8Q zXxn_rYOu0g3-QFd?!Y1_mXa-#gxW_s5Ap}Bk;l0j=8eqmxZKU9jF`4eYTb(VCpZie z_ebc^54^YN+(Lx1jVd^hUft&Jrar(>erMZkG%-lj#8bl$Yr4_@V_+1gAk1Gf0|O_M z6#srPF=!1>v+Zc9_D-!v-A|0f_34%F1{7dqzu$69c2?q>`i2W%txiYQ2Lem4En6fAlgi$4-rp9?$4)IsT&$#BSzff|Lcfs6| zVb7rvBlFz%JP{l(?y1H?*sNznfG|L%t&>AA&~+{e)W4a?k%@6X;hG(TKlGs&yVKo( zHZG_|TyMe^?BUD7{V>q28O$@sbs<7DMlsYqCaN^nOd3vw;>~VAG1$1z=Y8s1t0Ntx zhhY@=Mj`2~f8L`Z>15)|`vx7lzx+~3s+;>dkZ3d~=#ay}r%)gomU+74RnoNN*+Kpz zz^nj+;j>V&VLP)7@x2TJ_9l7_u~_1bNflamNwaYy7&n;HxgfIHfG28pc}baw0>!sJ zizS)c$p_@31_x(aD1xu6vVxgbIXxHi%jrMUuXA15sHlIE2vdJ@gvEF1*A64)fa)MY z<^RQpbjfj=?ehT)nsP!42tLfHYf{w|=|b|MlBWNWw<=?46yJydNz$C3?c3Xv&=0{r7<3#YCbFuPuV4h7xqs>Ski_(w*WkeNLkNCp#<|{exxAnIyMq3zcgA-kOEQgt>^hK(N)k3~(e!nuHN* zn1(O|r1Br_1H*1}GY4N5F`vBzYvCMcUTTsjFYWog~If0XEGH&F( zjp>R8hGP@`68t8DK-F3N)F$nD!!4S(r{b7b5Duw#HaJY9Ghbep4FHI7CC{aC5yIQs3)oX;=&B&P&$FnbcAa0eVGT7G<3IAZ)%?x3YclEt*)N)(%m z9~s;}!tvxC4i%kUq|&&O0x?|C+N5REoxl9w^Ul3`2=v0`?v&NW+I$}OqBfWvMAm?I z!+0RKv_01t-Dl;)(^xl`sSLt#{JcMJ-nJ2YIHokx-|w$rGkXg|gr=5jxyMS^%|_XM z-@oHFF?;`gKB{SQ*54hvqdpcPJ^}x|@2~xLv9%6I*|puI`8wNNc+Q?Hq?dh->l+MS zB$&A+GiBgE=_fkn$KLM_?g``_cANxBL$%n(8jnztB?wj5$c|NP4a8JTKEMX=v5H%U9lbP+3Kv-`tBFb%wx4;!Ph zxOz`x*%mEe&uxG`$3ebrol&FdNDz!%F%I1-v*K%&(T^}c71#elA>(a@E<$E+dXDZR zJur^a)W4ms&{oS?l&ALxLq3Hnu8?J_&m#SGMzv2E<^of|p-YjV;Dgt4PUfk+eRi%;cUB?&E-O?1{9%IpK#@Qy6;d;%Jlr`YC0%;ikJvid zpC{@@#9QFK23Pnv9BsJX$?pcH;GZ%2P7Z<{F3BLKF@;9CP!xmMoT+mIBLu*P(rMGb zlXA%ud9&AV$eM$rS{7kUDk=RmPMr*KmxwTke6TWC?`@p%&>6la=V77aRe8V(T1!|W zH3E5nz6enDHFMRuJZLSge3OQY_;GGm)Gb<+;-mtuemL`j0*k%3Id{3IiI}lOr_?GU zvJ;xSLO3WAU-=M2pcZUbuLR@%1nG0dAty78_82>_Wt!KN+^QKD~N8_y-Q%`|`Jmh5)&wj-+92wY*^a!Ot*N^5}Y0`WE z^IQYDZ@jRQxJ~#y7F%)#eMTAl7^MWVYAw>eBbMBPnt-RD6eCOO$+mF(#1`*FH(bvm#8)>g99WF@Kq$G&ZN=^Y zoP9CHs&cSX?Kw4~=4NX@V2w+MOynx;LD@r{HP5slg9;@&TAi|}V~6`IJ?YT&jyA0$ zS9DX#ao|tm&fc-_9gboKOuTYsZ8I$Ep09!#M4{x-gtTUk#Nv8Ld8Q^iD z$b@$km!$BYj*QB)f_dGn!*;hen)MsXekOV)?nc}k2qa`_{z9E%vr`2EbU}BN2!Mda}XkTau8TWY|894 z>Ae`8cv8goD&R(>VXXhyWXG1{gfcB=({(Bv1iy2uWp7OkTFo-p<|GIXLa4-Dl0!wM zl0nDX1}O>`Ph~UB+vdKHwmr-ajVF=qaZ7-^B)EepZ3Nc#upfr-sk4H)kaf8bH4Lwu zna#oe`O^&MHwi7I>6Z7();qj6qK%^Jdd3}=+W_Gzucv^U&RY|r-;EPNM4sysJtvqn zy&*mSt@L@=y0lxLa8ws;%z5wxeBaBD3PKA}u9Lb*ZHYE!Ua$B9Jc^V05_`|NP+z#6 z6Xlawu%7g&6G;J-8V^!n)ErB9ZrySnYzTDvdA-xioyVys;<93IRgzdQ(JpYPsj@6~ zyLrWUcm}vpnWM`DzmUsiZI-d?(5$HuqY>QYQ2Q^7xj~a6K?tAd7)<726ks(W8&1>5 zQG2(ON-ea-i-s71te~SU#}HCk0ce^=(%msb?PtHx=m7+_Ocy<_yO;Z6`}Mb7E(w5N zR6$yjQ@mzOM3Z4%ct2RzJR29YcM};YW!iq#q)lQiNSqd5h1ZLG5se!&owTIy+Q4YF znqZ{j&#_!M)c#yh@v0C&krjtf#?h}mewTt#J$%-87BN%XT0y}C?gjVytHcTCC;W!y zm4qBx{P{4|$0BWu`C1;xzZ%-y{n*cn_4M11~@%i?@|*b(-O!Ey29Gk^Eol)xpmL%^~J zI<0Pu{-LowGHU|F>km;DtKgf!A`Qx$$tB-OUhb_6?(z&>wxekvj@dMY2uH!r&w5AS z_5x3f&clS(5a3bC5~RyG;-I7;)#$^I_?&3ES?OV0kinf?Z3d@qcx_tRI3hygJ4@Vv zgIzM_S62%3KKYJKo!^^E8iWCoY`Vq6x_@pNhwIvXe&MgCS6{hgUDZe$LfuGkb=d%X39tIRsM0uaRFrAld(X_STsibvseZQMUR?eIYe=d~BwA!K0zs~dTt1Bawu0FRPB_MWpmxd6nTu(C%JH`*@xp3}!$F791R0RETW zdsCsqv6f8~i2<8ut9-q+OBNnyuFGDe_)nY)Ilw%4?TQt8i~Dt~3EP__>Na#XVPTfE zmGPU1pA57_s6E*uv&f)VyX5L>ccH0;^!|oF_Hj_gg>iU1SdGAJObDw|x2`-rWvR}7 zKVrHRSxKMQX$(7P!vi=tnaob=wC`MkH~86{lAi2c6eb1U)ar-#KiV`+g3l0Elsex9 zQckLFYYn0H>NjW}IUiT6QFqa6bh4fXin>g>nQ=5T$6*ZR>DahJgD=;$Eh1mlBxCdp z;CJfy!ZWM%B*Ag}YuuDtFxp!9jwl#`^hMs^Z$j|Q>JpBL5+>U4pI1X|2JNV0LFrws zVJR+`tGVKspl7!r_*(P-_Opg|@!s^$P60pI7_f|YJDhJJxzEIp2|~aY`$dYD0>$A_ zmO61?bAru+rex1UyFc0^+x^WcR;IgFrL;`(4}3V_mH2>Hc0q;#yZ`xpwYMFL6!{Kp zOO$s*??_!kI)&%m1>6Ex3mb7NrcSo9a!U)d#)#{KF#<%c?OEd)zmicON%jUnRMmFF z@+oT|ux>s5lq!qYUZERY`hf!n4q1S2o1K`h=06OML4k6jEa*TeCk>sc0P3BbNoHsp z*mPA|x9Mj!#d+;)qqw+;bj$<}pvNw@;(;0q9LAT4*C*W4iupLb zR@X7Q8;pRYXuqHrP(5Au(Lp*UO~l%zMFWQ}fBUe5Pz5wr8p`l{gDLW1J1*=qaShYt zw)i1-irS1iav`U>1=Yv}!|=`!yt4YI#od_um267Qm|AXnC038#MqU_fE0(-=dz=xF zIRVK=WIv^{YA~a4iC;%GMrr~Wa%!qc!?%IqHD@rf*^h8Lo5L*T`bXAHlcu)YN2WMl z7pVgl*y@i>@{Mfi7fkq9Cy5AUSG5}}L5f>PHV~=fZA4XLe+W+8iL9+*&~F1vMN19g zi6pv@xh_@qMMD`52CF2Ckkd8|&R=NpC57t$$HZ08T zuxBe`2#X)bulLyb4{)u$_!Adw)BxfZLR6HtFwGh49jJi{kmX2 z-mOGbm82VHjfL*;5WaBLxyn0_g*NTd|z3Yz^_hzN8UPQ=SMn9$=(AY_{ACz z<-&l^LxSjxotr_Jaz%05u$Y5h=9TGM_fC4-5FKKS=mkk}@Y?*pN$)15L=+HJll zI!_c!5Dqt2XOd%v-Izg_rfzbh$+U?C?}z)3ZTEIgle?j}J1)`!*H_OhAV-xu2pm!q z_ljaEM@kc$5vOqnF*ssXe_o{PwN9NAvNCC%2lK?44BBn2zzUl_EP+CXNBeSSEp$ee!}CicA6 zyr({b^pgYe;bmSn$7|zbGs@tPk+J6ET|7M;1asl~A7YMRjUz5u^3#4&OHjqF%f!1m zvP_eGIS;gbug|KOoTlcw1-*$)1ZXy`z`sEMDpGoL-Ozrm0-azH0cEfhj4aIq!iFcl zTNwu|aiNo0zYx?OQpGw!OB8_*-)09e%ZUHvO|v9YPBg-?=yS56=Kbm4JC+!BBwYBc zwN>!R$$GIQs07RPwg$Lkw9#ft&@2+ z%>Kk&yJE|^h2ZQvF5_Bgft3J4xy*Hk5V$cq!_qT#@^QB#GjDdNwt^rU_I>B`cw~R) z179MRQ!J(Pm5_qi&z?z91So9HOI(i zqDg3Hl56Z_BHHl!uepmpEmcui30OJzEuSD&cG*6JnROia#gY|d7z>JG4rXkApZ6>l z*4FEfQDfLCC`~>ezzu31ppd%?kRT2#KcWjs&!(p|dHB5*hxo2L@47}zaNFZ^^i;U3 z^qi@kG*oaV{;97Wfi?#>w34_el?AC%)v{sk*LPs2qehD^83_uQbU$t_8jVNNedUiJ z7ZxzZ>qLkeU%On5#1O^5LvU6~72Ll7MwQ~oV z0r(#Y@&F7BHU$hEh?(>s(*KzO3jRkS7!a)P|C=D*=E<(k#x_7LJy)B5`h@(C7Jsz? z{r>Otzxw%q^$QUQTn^};hLq-Jt}XyaXm0D``d1a8;ji9*bU`B6nOPYFWu$gy|NGvB z0>Qw%jMRJoX~_gKvvvNf1I*pZ%>2LkH`D;~4${Whj-T$XlIcV|PJo>ikCl z5eVG2G{C;mTl&9h{44&CPu$m6Ajbe`{Qz!;MEtr5hGq$%9E@Z!E#jIMY={^aIA9*K z+k?+{cW>=5OBYP@n1d~DD(cO z;FmzZ>HrVOAo&3L1dupDz&$`>02BofaQ%>g z7eV3yWCwUMpcw+_1LCc%27r?QbpbpsK!7(v0)4*KdAoK~hc^aDZ`a8Rkcpd_t1*B& zcIN*ez=Dzer_}?V;%w~b_-2^@Cox(5>snMLt`2VsiOh`uY5b-XOy1btf{TawJvTEO HE9-v&JnZ1n diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 53975e99e0..6a132802cb 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7770,6 +7770,8 @@ Sorry for the inconvenience."; "DeleteAccount.DeleteMyAccountTitle" = "Delete My Account"; "DeleteAccount.DeleteMyAccount" = "Delete My Account"; +"DeleteAccount.SavedMessages" = "Saved"; + "DeleteAccount.ComeBackLater" = "Come Back Later"; "DeleteAccount.Continue" = "Continue"; @@ -7778,10 +7780,18 @@ Sorry for the inconvenience."; "DeleteAccount.GroupsAndChannelsTitle" = "Your Groups and Channels"; "DeleteAccount.GroupsAndChannelsText" = "The groups and channels you created will either get new admins or become orphaned."; -"DeleteAccount.GroupsAndChannelsInfo" = "You can transfer group and channel ownership to other users via Chat Info > Edit > Admins. [More info]()"; +"DeleteAccount.GroupsAndChannelsInfo" = "You can transfer group and channel ownership to other users via Chat Info > Edit > Admins."; "DeleteAccount.MessageHistoryTitle" = "Your Message History"; -"DeleteAccount.MessageHistoryText" = "Your chat partners will keep their message history with you, including the messages you shared in secret chats.\n\nYou can remove any messages for both sides at any time, but this will not be possible if you delete your account. [More info]()"; +"DeleteAccount.MessageHistoryText" = "Your chat partners will keep their message history with you, including the messages you shared in secret chats.\n\nYou can remove any messages for both sides at any time, but this will not be possible if you delete your account."; + +"DeleteAccount.DeleteMessagesURL" = "https://telegram.org/faq#q-can-i-delete-my-messages"; + +"DeleteAccount.EnterPhoneNumber" = "Enter Your Phone Number"; +"DeleteAccount.InvalidPhoneNumberError" = "Invalid phone number. Please try again."; + +"DeleteAccount.EnterPassword" = "Enter Your Password"; +"DeleteAccount.InvalidPasswordError" = "Invalid password. Please try again."; "DeleteAccount.ConfirmationAlertTitle" = "Proceed to Delete Your Account?"; "DeleteAccount.ConfirmationAlertText" = "Deleting your account will permanently delete your data!\n\nIt is imposible to reverse this action!"; @@ -7801,3 +7811,8 @@ Sorry for the inconvenience."; "Premium.Gift.Years_1" = "%@ Year"; "Premium.Gift.Years_any" = "%@ Years"; + +"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."; diff --git a/submodules/ChatListUI/Sources/ChatListRecentPeersListItem.swift b/submodules/ChatListUI/Sources/ChatListRecentPeersListItem.swift index 4bef020a8b..fd1bc9b262 100644 --- a/submodules/ChatListUI/Sources/ChatListRecentPeersListItem.swift +++ b/submodules/ChatListUI/Sources/ChatListRecentPeersListItem.swift @@ -120,7 +120,7 @@ class ChatListRecentPeersListItemNode: ListViewItemNode { peersNode = currentPeersNode peersNode.updateThemeAndStrings(theme: item.theme, strings: item.strings) } else { - peersNode = ChatListSearchRecentPeersNode(context: item.context, theme: item.theme, mode: .list, strings: item.strings, peerSelected: { peer in + peersNode = ChatListSearchRecentPeersNode(context: item.context, theme: item.theme, mode: .list(compact: false), strings: item.strings, peerSelected: { peer in self?.item?.peerSelected(peer) }, peerContextAction: { peer, node, gesture in self?.item?.peerContextAction(peer, node, gesture) diff --git a/submodules/Display/Source/Navigation/NavigationController.swift b/submodules/Display/Source/Navigation/NavigationController.swift index eaacde87bd..43e43813bc 100644 --- a/submodules/Display/Source/Navigation/NavigationController.swift +++ b/submodules/Display/Source/Navigation/NavigationController.swift @@ -1271,7 +1271,7 @@ open class NavigationController: UINavigationController, ContainableController, let badgeNode = ASImageNode() badgeNode.displaysAsynchronously = false - badgeNode.image = UIImage(bundleImageName: "Components/BadgeTest") + badgeNode.image = UIImage(bundleImageName: "Components/AppBadge") self.badgeNode = badgeNode self.displayNode.addSubnode(badgeNode) } diff --git a/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift b/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift index 8f5d5d0928..5051bbe78f 100644 --- a/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift +++ b/submodules/HorizontalPeerItem/Sources/HorizontalPeerItem.swift @@ -12,7 +12,7 @@ import ContextUI import AccountContext public enum HorizontalPeerItemMode { - case list + case list(compact: Bool) case actionSheet } @@ -25,13 +25,13 @@ public final class HorizontalPeerItem: ListViewItem { let context: AccountContext public let peer: EnginePeer let action: (EnginePeer) -> Void - let contextAction: (EnginePeer, ASDisplayNode, ContextGesture?) -> Void + let contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?) -> Void)? let isPeerSelected: (EnginePeer.Id) -> Bool let customWidth: CGFloat? let presence: EnginePeer.Presence? let unreadBadge: (Int32, Bool)? - public init(theme: PresentationTheme, strings: PresentationStrings, mode: HorizontalPeerItemMode, context: AccountContext, peer: EnginePeer, presence: EnginePeer.Presence?, unreadBadge: (Int32, Bool)?, action: @escaping (EnginePeer) -> Void, contextAction: @escaping (EnginePeer, ASDisplayNode, ContextGesture?) -> Void, isPeerSelected: @escaping (EnginePeer.Id) -> Bool, customWidth: CGFloat?) { + public init(theme: PresentationTheme, strings: PresentationStrings, mode: HorizontalPeerItemMode, context: AccountContext, peer: EnginePeer, presence: EnginePeer.Presence?, unreadBadge: (Int32, Bool)?, action: @escaping (EnginePeer) -> Void, contextAction: ((EnginePeer, ASDisplayNode, ContextGesture?) -> Void)?, isPeerSelected: @escaping (EnginePeer.Id) -> Bool, customWidth: CGFloat?) { self.theme = theme self.strings = strings self.mode = mode @@ -111,11 +111,6 @@ public final class HorizontalPeerItemNode: ListViewItemNode { item.action(item.peer) } } - self.peerNode.contextAction = { [weak self] node, gesture in - if let item = self?.item { - item.contextAction(item.peer, node, gesture) - } - } } override public func didLoad() { @@ -186,10 +181,25 @@ public final class HorizontalPeerItemNode: ListViewItemNode { if let strongSelf = self { strongSelf.item = item strongSelf.peerNode.theme = itemTheme + if case let .list(compact) = item.mode { + strongSelf.peerNode.compact = compact + } else { + strongSelf.peerNode.compact = false + } strongSelf.peerNode.setup(context: item.context, theme: item.theme, strings: item.strings, peer: EngineRenderedPeer(peer: item.peer), numberOfLines: 1, synchronousLoad: synchronousLoads) strongSelf.peerNode.frame = CGRect(origin: CGPoint(), size: itemLayout.size) strongSelf.peerNode.updateSelection(selected: item.isPeerSelected(item.peer.id), animated: false) + if let contextAction = item.contextAction { + strongSelf.peerNode.contextAction = { [weak item] node, gesture in + if let item = item { + contextAction(item.peer, node, gesture) + } + } + } else { + strongSelf.peerNode.contextAction = nil + } + let badgeBackgroundWidth: CGFloat if let currentBadgeBackgroundImage = currentBadgeBackgroundImage { strongSelf.badgeBackgroundNode.image = currentBadgeBackgroundImage diff --git a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift index 6c7a0d04db..e5bdbe1cde 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift @@ -113,8 +113,9 @@ class InviteLinkHeaderItemNode: ListViewItemNode { let makeTextLayout = TextNode.asyncLayout(self.textNode) return { item, params, neighbors in - let leftInset: CGFloat = 28.0 + params.leftInset - let topInset: CGFloat = 124.0 + let leftInset: CGFloat = 24.0 + params.leftInset + let iconSize = CGSize(width: 140.0, height: 140.0) + let topInset: CGFloat = iconSize.height - 4.0 let spacing: CGFloat = 5.0 let attributedTitle = NSAttributedString(string: item.title ?? "", font: titleFont, textColor: item.theme.list.itemPrimaryTextColor, paragraphAlignment: .center) @@ -123,9 +124,9 @@ class InviteLinkHeaderItemNode: ListViewItemNode { return (TelegramTextAttributes.URL, contents) })) - let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedTitle, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + let (titleLayout, titleApply) = makeTitleLayout(TextNodeLayoutArguments(attributedString: attributedTitle, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) - let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - params.rightInset - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) + let (textLayout, textApply) = makeTextLayout(TextNodeLayoutArguments(attributedString: attributedText, backgroundColor: nil, maximumNumberOfLines: 0, truncationType: .end, constrainedSize: CGSize(width: params.width - leftInset * 2.0, height: CGFloat.greatestFiniteMagnitude), alignment: .center, cutout: nil, insets: UIEdgeInsets())) var contentSize = CGSize(width: params.width, height: topInset + textLayout.size.height) if let _ = item.title { @@ -138,13 +139,12 @@ class InviteLinkHeaderItemNode: ListViewItemNode { return (layout, { [weak self] in if let strongSelf = self { if strongSelf.item == nil { - strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: item.animationName), width: 192, height: 192, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) + strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: item.animationName), width: 256, height: 256, playbackMode: .loop, mode: .direct(cachePathPrefix: nil)) strongSelf.animationNode.visibility = true } strongSelf.item = item strongSelf.accessibilityLabel = attributedText.string - let iconSize = CGSize(width: 128.0, height: 128.0) strongSelf.animationNode.frame = CGRect(origin: CGPoint(x: floor((layout.size.width - iconSize.width) / 2.0), y: -10.0), size: iconSize) strongSelf.animationNode.updateLayout(size: iconSize) diff --git a/submodules/PremiumUI/Sources/GiftAvatarComponent.swift b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift index 9069fab68b..f5fe398dd5 100644 --- a/submodules/PremiumUI/Sources/GiftAvatarComponent.swift +++ b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift @@ -275,9 +275,8 @@ class GiftAvatarComponent: Component { } self.hasIdleAnimations = component.hasIdleAnimations - let avatarSize = CGSize(width: 100.0, height: 100.0) - self.avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: component.peer, size: avatarSize, font: avatarPlaceholderFont(size: 78.0), fullSize: true)) + self.avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: component.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 diff --git a/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift b/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift index 48643b1b3b..c590dfa764 100644 --- a/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift +++ b/submodules/SelectablePeerNode/Sources/SelectablePeerNode.swift @@ -84,6 +84,8 @@ public final class SelectablePeerNode: ASDisplayNode { private var peer: EngineRenderedPeer? + public var compact = false + public var theme: SelectablePeerNodeTheme = SelectablePeerNodeTheme(textColor: .black, secretTextColor: .green, selectedTextColor: .blue, checkBackgroundColor: .white, checkFillColor: .blue, checkColor: .white, avatarPlaceholderColor: .white) { didSet { if !self.theme.isEqual(to: oldValue) { @@ -147,7 +149,7 @@ public final class SelectablePeerNode: ASDisplayNode { let text: String var overrideImage: AvatarNodeImageOverride? if peer.peerId == context.account.peerId { - text = strings.DialogList_SavedMessages + text = self.compact ? strings.DeleteAccount_SavedMessages : strings.DialogList_SavedMessages overrideImage = .savedMessagesIcon } else if peer.peerId.isReplies { text = strings.DialogList_Replies diff --git a/submodules/SettingsUI/BUILD b/submodules/SettingsUI/BUILD index 3e2c5fb18d..6f77d2566e 100644 --- a/submodules/SettingsUI/BUILD +++ b/submodules/SettingsUI/BUILD @@ -102,6 +102,7 @@ swift_library( "//submodules/PaymentMethodUI:PaymentMethodUI", "//submodules/PremiumUI:PremiumUI", "//submodules/InviteLinksUI:InviteLinksUI", + "//submodules/HorizontalPeerItem:HorizontalPeerItem", ], visibility = [ "//visibility:public", diff --git a/submodules/SettingsUI/Sources/ChangePhoneNumberControllerNode.swift b/submodules/SettingsUI/Sources/ChangePhoneNumberControllerNode.swift index 9903e8b9ff..41ea069963 100644 --- a/submodules/SettingsUI/Sources/ChangePhoneNumberControllerNode.swift +++ b/submodules/SettingsUI/Sources/ChangePhoneNumberControllerNode.swift @@ -286,5 +286,4 @@ final class ChangePhoneNumberControllerNode: ASDisplayNode { @objc func countryPressed() { self.selectCountryCode?() } - } diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index 9c1886c473..8396eb6eb5 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -13,25 +13,47 @@ import AlertUI import PresentationDataUtils import UrlHandling import InviteLinksUI +import CountrySelectionUI +import PhoneInputNode private struct DeleteAccountDataArguments { let context: AccountContext let openLink: (String) -> Void + let selectCountryCode: () -> Void + let updatePassword: (String) -> Void + let proceed: () -> Void } private enum DeleteAccountDataSection: Int32 { + case header case main } +private enum DeleteAccountEntryTag: Equatable, ItemListItemTag { + case password + + func isEqual(to other: ItemListItemTag) -> Bool { + if let other = other as? DeleteAccountEntryTag { + return self == other + } else { + return false + } + } +} + + private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { case header(PresentationTheme, String, String, String) - - case peers(PresentationTheme, [Peer]) + case peers(PresentationTheme, [EnginePeer]) + case phone(PresentationTheme, PresentationStrings) + case password(PresentationTheme, String) case info(PresentationTheme, String) var section: ItemListSectionId { switch self { - case .header, .peers, .info: + case .header: + return DeleteAccountDataSection.header.rawValue + case .peers, .info, .phone, .password: return DeleteAccountDataSection.main.rawValue } } @@ -43,7 +65,11 @@ private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { case .peers: return 1 case .info: + return 2 + case .phone: return 3 + case .password: + return 4 } } @@ -56,7 +82,7 @@ private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { return false } case let .peers(lhsTheme, lhsPeers): - if case let .peers(rhsTheme, rhsPeers) = rhs, lhsTheme === rhsTheme, arePeerArraysEqual(lhsPeers, rhsPeers) { + if case let .peers(rhsTheme, rhsPeers) = rhs, lhsTheme === rhsTheme, lhsPeers == rhsPeers { return true } else { return false @@ -67,6 +93,19 @@ private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { } else { return false } + case let .phone(lhsTheme, lhsStrings): + if case let .phone(rhsTheme, rhsStrings) = rhs, lhsTheme === rhsTheme, lhsStrings === rhsStrings { + return true + } else { + return false + } + case let .password(lhsTheme, lhsPlaceholder): + if case let .password(rhsTheme, rhsPlaceholder) = rhs, lhsTheme === rhsTheme, lhsPlaceholder == rhsPlaceholder { + return true + } else { + return false + } + } } @@ -80,14 +119,26 @@ private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { case let .header(theme, animation, title, text): return InviteLinkHeaderItem(context: arguments.context, theme: theme, title: title, text: text, animationName: animation, sectionId: self.section, linkAction: nil) case let .peers(_, peers): - return ItemListTextItem(presentationData: presentationData, text: .plain(peers.first?.debugDisplayTitle ?? ""), sectionId: self.section) + return DeleteAccountPeersItem(context: arguments.context, theme: presentationData.theme, strings: presentationData.strings, peers: peers, sectionId: self.section) case let .info(_, text): return ItemListTextItem(presentationData: presentationData, text: .markdown(text), sectionId: self.section) + case .phone: + return DeleteAccountPhoneItem(theme: presentationData.theme, strings: presentationData.strings, value: (nil, nil, ""), sectionId: self.section, selectCountryCode: { + arguments.selectCountryCode() + }, updated: { _ in + + }) + case let .password(_, placeholder): + return ItemListSingleLineInputItem(presentationData: presentationData, title: NSAttributedString(), text: "", placeholder: placeholder, type: .password, returnKeyType: .done, tag: DeleteAccountEntryTag.password, sectionId: self.section, textUpdated: { value in + arguments.updatePassword(value) + }, action: { + arguments.proceed() + }) } } } -private func deleteAccountDataEntries(presentationData: PresentationData, mode: DeleteAccountDataMode, peers: [Peer]) -> [DeleteAccountDataEntry] { +private func deleteAccountDataEntries(presentationData: PresentationData, mode: DeleteAccountDataMode, peers: [EnginePeer]) -> [DeleteAccountDataEntry] { var entries: [DeleteAccountDataEntry] = [] let headerTitle: String @@ -96,24 +147,45 @@ private func deleteAccountDataEntries(presentationData: PresentationData, mode: switch mode { case .peers: - headerAnimation = "" + headerAnimation = "Delete1" headerTitle = presentationData.strings.DeleteAccount_CloudStorageTitle headerText = presentationData.strings.DeleteAccount_CloudStorageText case .groups: - headerAnimation = "" + headerAnimation = "Delete2" headerTitle = presentationData.strings.DeleteAccount_GroupsAndChannelsTitle headerText = presentationData.strings.DeleteAccount_GroupsAndChannelsText case .messages: - headerAnimation = "" + headerAnimation = "Delete3" headerTitle = presentationData.strings.DeleteAccount_MessageHistoryTitle headerText = presentationData.strings.DeleteAccount_MessageHistoryText + case .phone: + headerAnimation = "Delete4" + headerTitle = presentationData.strings.DeleteAccount_EnterPhoneNumber + headerText = "" + case .password: + headerAnimation = "Delete5" + headerTitle = presentationData.strings.DeleteAccount_EnterPassword + headerText = "" } entries.append(.header(presentationData.theme, headerAnimation, headerTitle, headerText)) - entries.append(.peers(presentationData.theme, peers)) - if case .groups = mode { - entries.append(.info(presentationData.theme, presentationData.strings.DeleteAccount_GroupsAndChannelsInfo)) + switch mode { + case .peers: + if !peers.isEmpty { + entries.append(.peers(presentationData.theme, peers)) + } + case .groups: + if !peers.isEmpty { + entries.append(.peers(presentationData.theme, peers)) + entries.append(.info(presentationData.theme, presentationData.strings.DeleteAccount_GroupsAndChannelsInfo)) + } + case .messages: + break + case .phone: + entries.append(.phone(presentationData.theme, presentationData.strings)) + case .password: + entries.append(.password(presentationData.theme, presentationData.strings.LoginPassword_PasswordPlaceholder)) } return entries @@ -121,55 +193,150 @@ private func deleteAccountDataEntries(presentationData: PresentationData, mode: enum DeleteAccountDataMode { case peers - case groups + case groups([EnginePeer]) case messages + case phone + case password } -func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDataMode) -> ViewController { +private struct DeleteAccountDataState: Equatable { + var password: String + var isLoading: Bool + + static func == (lhs: DeleteAccountDataState, rhs: DeleteAccountDataState) -> Bool { + return lhs.password == rhs.password && lhs.isLoading == rhs.isLoading + } +} + +func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDataMode, twoStepAuthData: TwoStepVerificationAccessConfiguration?) -> ViewController { + let initialState = DeleteAccountDataState(password: "", isLoading: false) + let statePromise = ValuePromise(initialState, ignoreRepeated: true) + let stateValue = Atomic(value: initialState) + let updateState: ((DeleteAccountDataState) -> DeleteAccountDataState) -> Void = { f in + statePromise.set(stateValue.modify { f($0) }) + } + + var presentControllerImpl: ((ViewController) -> Void)? + var pushControllerImpl: ((ViewController) -> Void)? var replaceTopControllerImpl: ((ViewController) -> Void)? var dismissImpl: (() -> Void)? + var updateCodeImpl: (() -> Void)? + + var activateInputImpl: (() -> Void)? + var dismissInputImpl: (() -> Void)? + + if case .phone = mode { + loadServerCountryCodes(accountManager: context.sharedContext.accountManager, engine: context.engine, completion: { + updateCodeImpl?() + }) + } + var updateCountryCodeImpl: ((Int32, String) -> Void)? + var proceedImpl: (() -> Void)? + let arguments = DeleteAccountDataArguments(context: context, openLink: { _ in + }, selectCountryCode: { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let controller = AuthorizationSequenceCountrySelectionController(strings: presentationData.strings, theme: presentationData.theme) + controller.completeWithCountryCode = { code, name in + updateCountryCodeImpl?(Int32(code), name) + activateInputImpl?() + } + dismissInputImpl?() + pushControllerImpl?(controller) + }, updatePassword: { password in + updateState { current in + var updated = current + updated.password = password + return updated + } + }, proceed: { + proceedImpl?() }) - let peers: Signal<[Peer], NoError> = .single([]) - + let preloadedGroupPeers = Promise<[EnginePeer]>([]) + + let peers: Signal<[EnginePeer], NoError> + switch mode { + case .peers: + peers = combineLatest( + context.engine.peers.recentPeers() + |> map { recentPeers -> [EnginePeer] in + if case let .peers(peers) = recentPeers { + return peers.map { EnginePeer($0) } + } else { + return [] + } + }, + context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + ) |> map { recentPeers, accountPeer -> [EnginePeer] in + var peers: [EnginePeer] = [] + if let accountPeer = accountPeer { + peers.append(accountPeer) + } + peers.append(contentsOf: recentPeers.prefix(9)) + return peers + } + + preloadedGroupPeers.set(context.engine.peers.adminedPublicChannels(scope: .all) + |> map { peers -> [EnginePeer] in + return peers.map { EnginePeer($0) } + }) + case let .groups(preloadedPeers): + peers = .single(preloadedPeers.shuffled()) + default: + peers = .single([]) + } + let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, - peers + peers, + statePromise.get() ) - |> map { presentationData, peers -> (ItemListControllerState, (ItemListNodeState, Any)) in + |> map { presentationData, peers, state -> (ItemListControllerState, (ItemListNodeState, Any)) in let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { dismissImpl?() }) - let footerItem = DeleteAccountFooterItem(theme: presentationData.theme, title: presentationData.strings.DeleteAccount_ComeBackLater, secondaryTitle: presentationData.strings.DeleteAccount_Continue, action: { + var focusItemTag: DeleteAccountEntryTag? + var buttonTitle: String + switch mode { + case .phone: + buttonTitle = "" + case .password: + buttonTitle = "" + focusItemTag = .password + default: + buttonTitle = presentationData.strings.DeleteAccount_ComeBackLater + } + + let rightNavigationButton: ItemListNavigationButton? + if state.isLoading { + rightNavigationButton = ItemListNavigationButton(content: .none, style: .activity, enabled: true, action: {}) + } else { + rightNavigationButton = nil + } + + let footerItem = DeleteAccountFooterItem(theme: presentationData.theme, title: buttonTitle, secondaryTitle: presentationData.strings.DeleteAccount_Continue, action: { dismissImpl?() }, secondaryAction: { - let nextMode: DeleteAccountDataMode? - switch mode { - case .peers: - nextMode = .groups - case .groups: - nextMode = .messages - case .messages: - nextMode = nil - } - - if let nextMode = nextMode { - let controller = deleteAccountDataController(context: context, mode: nextMode) - replaceTopControllerImpl?(controller) - } + proceedImpl?() }) - let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.DeleteAccount_DeleteMyAccountTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: nil, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) - let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: deleteAccountDataEntries(presentationData: presentationData, mode: mode, peers: peers), style: .blocks, footerItem: footerItem) + let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.DeleteAccount_DeleteMyAccountTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) + let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: deleteAccountDataEntries(presentationData: presentationData, mode: mode, peers: peers), style: .blocks, focusItemTag: focusItemTag, footerItem: footerItem) return (controllerState, (listState, arguments)) } let controller = ItemListController(context: context, state: signal, tabBarItem: nil) + presentControllerImpl = { [weak controller] c in + controller?.present(c, in: .window(.root)) + } + pushControllerImpl = { [weak controller] c in + controller?.push(c) + } replaceTopControllerImpl = { [weak controller] c in if let navigationController = controller?.navigationController as? NavigationController { navigationController.pushViewController(c, completion: { [weak navigationController, weak controller, weak c] in @@ -184,7 +351,172 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat dismissImpl = { [weak controller] in let _ = controller?.dismiss() } - + updateCodeImpl = { [weak controller] in + controller?.forEachItemNode { itemNode in + if let itemNode = itemNode as? DeleteAccountPhoneItemNode { + itemNode.updateCountryCode() + } + } + } + + activateInputImpl = { [weak controller] in + controller?.forEachItemNode { itemNode in + if let itemNode = itemNode as? DeleteAccountPhoneItemNode { + itemNode.activateInput() + } + } + } + dismissInputImpl = { [weak controller] in + controller?.view.endEditing(true) + } + controller.didAppear = { firstTime in + if !firstTime { + return + } + activateInputImpl?() + } + + updateCountryCodeImpl = { [weak controller] code, name in + controller?.forEachItemNode { itemNode in + if let itemNode = itemNode as? DeleteAccountPhoneItemNode { + itemNode.updateCountryCode(code: code, name: name) + } + } + } + + proceedImpl = { [weak controller] in + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + let action: ([EnginePeer]) -> Void = { preloadedPeers in + let nextMode: DeleteAccountDataMode? + switch mode { + case .peers: + if !preloadedPeers.isEmpty { + nextMode = .groups(preloadedPeers) + } else { + nextMode = .messages + } + case .groups: + nextMode = .messages + case .messages: + nextMode = .phone + case .phone: + if let twoStepAuthData = twoStepAuthData, case .set = twoStepAuthData { + nextMode = .password + } else { + nextMode = nil + } + case .password: + nextMode = nil + } + + if let nextMode = nextMode { + let controller = deleteAccountDataController(context: context, mode: nextMode, twoStepAuthData: twoStepAuthData) + replaceTopControllerImpl?(controller) + } else { + presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.DeleteAccount_ConfirmationAlertTitle, text: presentationData.strings.DeleteAccount_ConfirmationAlertText, actions: [TextAlertAction(type: .destructiveAction, title: presentationData.strings.DeleteAccount_ConfirmationAlertDelete, action: { + updateState { current in + var updated = current + updated.isLoading = true + return updated + } + + let accountId = context.account.id + let accountManager = context.sharedContext.accountManager + let _ = (context.engine.auth.deleteAccount(reason: "Manual") + |> deliverOnMainQueue).start(error: { _ in + updateState { current in + var updated = current + updated.isLoading = false + return updated + } + + presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])) + }, completed: { + dismissImpl?() + let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: true).start() + }) + }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: { + dismissImpl?() + })])) + } + } + + switch mode { + case .peers: + let _ = (preloadedGroupPeers.get() + |> take(1) + |> deliverOnMainQueue).start(next: { peers in + action(peers) + }) + case .phone: + var phoneNumber: String? + controller?.forEachItemNode { itemNode in + if let itemNode = itemNode as? DeleteAccountPhoneItemNode { + phoneNumber = itemNode.phoneNumber + } + } + + if let phoneNumber = phoneNumber, phoneNumber.count > 4 { + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)) + |> deliverOnMainQueue) + .start(next: { accountPeer in + if let accountPeer = accountPeer, case let .user(user) = accountPeer, var phone = user.phone { + if !phone.hasPrefix("+") { + phone = "+\(phone)" + } + if phone != phoneNumber { + presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.DeleteAccount_InvalidPhoneNumberError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])) + return + } + action([]) + } + }) + } + case .password: + let state = stateValue.with { $0 } + if !state.password.isEmpty { + updateState { current in + var updated = current + updated.isLoading = true + return updated + } + + let _ = (context.engine.auth.requestTwoStepVerifiationSettings(password: state.password) + |> deliverOnMainQueue).start(error: { error in + updateState { current in + var updated = current + updated.isLoading = false + return updated + } + + let text: String + switch error { + case .limitExceeded: + text = presentationData.strings.LoginPassword_FloodError + case .invalidPassword: + text = presentationData.strings.DeleteAccount_InvalidPasswordError + default: + text = presentationData.strings.Login_UnknownError + } + presentControllerImpl?(textAlertController(context: context, title: nil, text: text, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])) + }, completed: { + updateState { current in + var updated = current + updated.isLoading = false + return updated + } + + action([]) + }) + return + } + + default: + action([]) + } + } + return controller } diff --git a/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift b/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift index 208bd12c34..b5b9f04b34 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift @@ -44,8 +44,9 @@ final class DeleteAccountFooterItem: ItemListControllerFooterItem { final class DeleteAccountFooterItemNode: ItemListControllerFooterItemNode { private let backgroundNode: NavigationBackgroundNode private let separatorNode: ASDisplayNode + private let clipNode: ASDisplayNode private let buttonNode: SolidRoundedButtonNode - private let secondaryButtonNode: HighlightTrackingButtonNode + private let secondaryButtonNode: HighlightableButtonNode private var validLayout: ContainerViewLayout? @@ -64,16 +65,20 @@ final class DeleteAccountFooterItemNode: ItemListControllerFooterItemNode { self.backgroundNode = NavigationBackgroundNode(color: item.theme.rootController.tabBar.backgroundColor) self.separatorNode = ASDisplayNode() + self.clipNode = ASDisplayNode() + self.clipNode.clipsToBounds = true + self.buttonNode = SolidRoundedButtonNode(theme: SolidRoundedButtonTheme(backgroundColor: .black, foregroundColor: .white), height: 50.0, cornerRadius: 11.0, gloss: true) - self.secondaryButtonNode = HighlightTrackingButtonNode() + self.secondaryButtonNode = HighlightableButtonNode() super.init() self.addSubnode(self.backgroundNode) self.addSubnode(self.separatorNode) - self.addSubnode(self.buttonNode) - self.addSubnode(self.secondaryButtonNode) + self.addSubnode(self.clipNode) + self.clipNode.addSubnode(self.buttonNode) + self.clipNode.addSubnode(self.secondaryButtonNode) self.secondaryButtonNode.addTarget(self, action: #selector(self.secondaryButtonPressed), forControlEvents: .touchUpInside) @@ -121,8 +126,19 @@ final class DeleteAccountFooterItemNode: ItemListControllerFooterItemNode { let secondaryButtonSize = self.secondaryButtonNode.measure(CGSize(width: buttonWidth, height: CGFloat.greatestFiniteMagnitude)) var panelHeight: CGFloat = buttonHeight + topInset + spacing + secondaryButtonSize.height + bottomInset + + var buttonOffset: CGFloat = 0.0 let totalPanelHeight: CGFloat + + if (self.buttonNode.title?.isEmpty ?? false) { + buttonOffset = -buttonHeight - topInset + self.buttonNode.alpha = 0.0 + } else { + self.buttonNode.alpha = 1.0 + } + if let inputHeight = layout.inputHeight, inputHeight > 0.0 { + panelHeight += buttonOffset totalPanelHeight = panelHeight + insets.bottom } else { panelHeight += insets.bottom @@ -130,13 +146,15 @@ final class DeleteAccountFooterItemNode: ItemListControllerFooterItemNode { } let panelFrame = CGRect(origin: CGPoint(x: 0.0, y: layout.size.height - totalPanelHeight), size: CGSize(width: layout.size.width, height: panelHeight)) - transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + buttonInset, y: panelFrame.minY + topInset), size: CGSize(width: buttonWidth, height: buttonHeight))) - - transition.updateFrame(node: self.secondaryButtonNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - secondaryButtonSize.width) / 2.0), y: panelFrame.minY + topInset + buttonHeight + spacing), size: secondaryButtonSize)) transition.updateFrame(node: self.backgroundNode, frame: panelFrame) self.backgroundNode.update(size: panelFrame.size, transition: transition) + transition.updateFrame(node: self.clipNode, frame: panelFrame) + + transition.updateFrame(node: self.buttonNode, frame: CGRect(origin: CGPoint(x: layout.safeInsets.left + buttonInset, y: topInset + buttonOffset), size: CGSize(width: buttonWidth, height: buttonHeight))) + transition.updateFrame(node: self.secondaryButtonNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((layout.size.width - secondaryButtonSize.width) / 2.0), y: topInset + buttonHeight + spacing + buttonOffset), size: secondaryButtonSize)) + transition.updateFrame(node: self.separatorNode, frame: CGRect(origin: panelFrame.origin, size: CGSize(width: panelFrame.width, height: UIScreenPixel))) return panelHeight diff --git a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift index 7325104044..bc3d7f50e1 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift @@ -15,14 +15,17 @@ import PresentationDataUtils import UrlHandling import AccountUtils import PremiumUI +import PasswordSetupUI private struct DeleteAccountOptionsArguments { let changePhoneNumber: () -> Void let addAccount: () -> Void let setupPrivacy: () -> Void - let setTwoStepAuth: () -> Void + let setupTwoStepAuth: () -> Void let setPasscode: () -> Void let clearCache: () -> Void + let clearSyncedContacts: () -> Void + let deleteChats: () -> Void let contactSupport: () -> Void let deleteAccount: () -> Void } @@ -111,8 +114,8 @@ private enum DeleteAccountOptionsEntry: ItemListNodeEntry, Equatable { arguments.setupPrivacy() }) case let .setTwoStepAuth(_, title, text): - return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.setPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.setTwoStepAuth() + return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.deleteSetTwoStepAuth, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { + arguments.setupTwoStepAuth() }) case let .setPasscode(_, title, text): return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.deleteSetPasscode, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { @@ -124,11 +127,11 @@ private enum DeleteAccountOptionsEntry: ItemListNodeEntry, Equatable { }) case let .clearSyncedContacts(_, title, text): return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.clearSynced, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.clearCache() + arguments.clearSyncedContacts() }) case let .deleteChats(_, title, text): return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.deleteChats, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { - arguments.clearCache() + arguments.deleteChats() }) case let .contactSupport(_, title, text): return ItemListDisclosureItem(presentationData: presentationData, icon: PresentationResourcesSettings.support, title: title, label: text, labelStyle: .multilineDetailText, sectionId: self.section, style: .blocks, disclosureStyle: .arrow, action: { @@ -168,14 +171,14 @@ private func deleteAccountOptionsEntries(presentationData: PresentationData, can return entries } -public func deleteAccountOptionsController(context: AccountContext, navigationController: NavigationController, hasTwoStepAuth: Bool) -> ViewController { +public func deleteAccountOptionsController(context: AccountContext, navigationController: NavigationController, hasTwoStepAuth: Bool, twoStepAuthData: TwoStepVerificationAccessConfiguration?) -> ViewController { var pushControllerImpl: ((ViewController) -> Void)? var presentControllerImpl: ((ViewController, Any?) -> Void)? var replaceTopControllerImpl: ((ViewController, Bool) -> Void)? var dismissImpl: (() -> Void)? let supportPeerDisposable = MetaDisposable() - + let arguments = DeleteAccountOptionsArguments(changePhoneNumber: { let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.engine.account.peerId)) |> deliverOnMainQueue).start(next: { accountPeer in @@ -224,9 +227,30 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo } }) }, setupPrivacy: { + replaceTopControllerImpl?(makePrivacyAndSecurityController(context: context), false) + }, setupTwoStepAuth: { + if let data = twoStepAuthData { + switch data { + case .set: + break + case let .notSet(pendingEmail): + if pendingEmail == nil { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let controller = TwoFactorAuthSplashScreen(sharedContext: context.sharedContext, engine: .authorized(context.engine), mode: .intro(.init( + title: presentationData.strings.TwoFactorSetup_Intro_Title, + text: presentationData.strings.TwoFactorSetup_Intro_Text, + actionText: presentationData.strings.TwoFactorSetup_Intro_Action, + doneText: presentationData.strings.TwoFactorSetup_Done_Action + ))) - }, setTwoStepAuth: { + replaceTopControllerImpl?(controller, false) + return + } + } + } + let controller = twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: twoStepAuthData.flatMap({ Signal.single(.access(configuration: $0)) }))) + replaceTopControllerImpl?(controller, false) }, setPasscode: { let _ = passcodeOptionsAccessController(context: context, pushController: { controller in replaceTopControllerImpl?(controller, false) @@ -241,11 +265,44 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo }, clearCache: { pushControllerImpl?(storageUsageController(context: context)) dismissImpl?() + }, clearSyncedContacts: { + replaceTopControllerImpl?(dataPrivacyController(context: context), false) + }, deleteChats: { + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + + var faqUrl = presentationData.strings.DeleteAccount_DeleteMessagesURL + if faqUrl == "DeleteAccount.DeleteMessagesURL" || faqUrl.isEmpty { + faqUrl = "https://telegram.org/faq#q-can-i-delete-my-messages" + } + let resolvedUrl = resolveInstantViewUrl(account: context.account, url: faqUrl) + + let resolvedUrlPromise = Promise() + resolvedUrlPromise.set(resolvedUrl) + + let openFaq: (Promise) -> Void = { resolvedUrl in + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let controller = OverlayStatusController(theme: presentationData.theme, type: .loading(cancelled: nil)) + presentControllerImpl?(controller, nil) + let _ = (resolvedUrl.get() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak controller] resolvedUrl in + controller?.dismiss() + dismissImpl?() + + context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peer, navigation in + }, sendFile: nil, sendSticker: nil, requestMessageActionUrlAuth: nil, joinVoiceChat: nil, present: { controller, arguments in + pushControllerImpl?(controller) + }, dismissInput: {}, contentContext: nil) + }) + } + + openFaq(resolvedUrlPromise) }, contactSupport: { [weak navigationController] in + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + let supportPeer = Promise() supportPeer.set(context.engine.peers.supportPeerId()) - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - + var faqUrl = presentationData.strings.Settings_FAQ_URL if faqUrl == "Settings.FAQ_URL" || faqUrl.isEmpty { faqUrl = "https://telegram.org/faq#general" @@ -289,7 +346,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo }) ]), nil) }, deleteAccount: { - let controller = deleteAccountDataController(context: context, mode: .peers) + let controller = deleteAccountDataController(context: context, mode: .peers, twoStepAuthData: twoStepAuthData) replaceTopControllerImpl?(controller, true) }) @@ -337,7 +394,18 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo } }) } else { - navigationController?.replaceTopController(c, animated: true) + if c is PrivacyAndSecurityControllerImpl { + if let navigationController = navigationController { + if let existing = navigationController.viewControllers.first(where: { $0 is PrivacyAndSecurityControllerImpl }) as? ViewController { + existing.scrollToTop?() + dismissImpl?() + } else { + navigationController.replaceTopController(c, animated: true) + } + } + } else { + navigationController?.replaceTopController(c, animated: true) + } } } dismissImpl = { [weak controller] in diff --git a/submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift b/submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift new file mode 100644 index 0000000000..f5c1b34c52 --- /dev/null +++ b/submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift @@ -0,0 +1,296 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import TelegramCore +import TelegramPresentationData +import TelegramUIPreferences +import ItemListUI +import PresentationDataUtils +import HorizontalPeerItem +import AccountContext +import MergeLists + +private struct PeersEntry: Comparable, Identifiable { + let index: Int + let peer: EnginePeer + let theme: PresentationTheme + let strings: PresentationStrings + + var stableId: EnginePeer.Id { + return self.peer.id + } + + static func ==(lhs: PeersEntry, rhs: PeersEntry) -> Bool { + if lhs.index != rhs.index { + return false + } + if lhs.peer != rhs.peer { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.strings !== rhs.strings { + return false + } + return true + } + + static func <(lhs: PeersEntry, rhs: PeersEntry) -> Bool { + return lhs.index < rhs.index + } + + func item(context: AccountContext) -> ListViewItem { + return HorizontalPeerItem(theme: self.theme, strings: self.strings, mode: .list(compact: true), context: context, peer: self.peer, presence: nil, unreadBadge: nil, action: { _ in }, contextAction: nil, isPeerSelected: { _ in return false }, customWidth: nil) + } +} + +private struct DeleteAccountPeersItemNodeTransition { + let deletions: [ListViewDeleteItem] + let insertions: [ListViewInsertItem] + let updates: [ListViewUpdateItem] + let firstTime: Bool + let animated: Bool +} + +private func preparedPeersTransition(context: AccountContext, from fromEntries: [PeersEntry], to toEntries: [PeersEntry], firstTime: Bool, animated: Bool) -> DeleteAccountPeersItemNodeTransition { + 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(context: context), directionHint: .Down) } + let updates = updateIndices.map { ListViewUpdateItem(index: $0.0, previousIndex: $0.2, item: $0.1.item(context: context), directionHint: nil) } + + return DeleteAccountPeersItemNodeTransition(deletions: deletions, insertions: insertions, updates: updates, firstTime: firstTime, animated: animated) +} + +class DeleteAccountPeersItem: ListViewItem, ItemListItem { + var sectionId: ItemListSectionId + + let context: AccountContext + let theme: PresentationTheme + let strings: PresentationStrings + let peers: [EnginePeer] + + init(context: AccountContext, theme: PresentationTheme, strings: PresentationStrings, peers: [EnginePeer], sectionId: ItemListSectionId) { + self.context = context + self.theme = theme + self.strings = strings + self.peers = peers + self.sectionId = sectionId + } + + func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + async { + let node = DeleteAccountPeersItemNode() + let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + + node.contentSize = layout.contentSize + node.insets = layout.insets + + Queue.mainQueue().async { + completion(node, { + return (nil, { _ in apply() }) + }) + } + } + } + + func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) { + Queue.mainQueue().async { + if let nodeValue = node() as? DeleteAccountPeersItemNode { + let makeLayout = nodeValue.asyncLayout() + + async { + let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + Queue.mainQueue().async { + completion(layout, { _ in + apply() + }) + } + } + } + } + } +} + +class DeleteAccountPeersItemNode: ListViewItemNode, ItemListItemNode { + private let backgroundNode: ASDisplayNode + private let topStripeNode: ASDisplayNode + private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode + + private let dataPromise = Promise<(AccountContext, [EnginePeer], PresentationTheme, PresentationStrings)>() + private var disposable: Disposable? + + private var item: DeleteAccountPeersItem? + private var layoutParams: ListViewItemLayoutParams? + + private let listView: ListView + private var queuedTransitions: [DeleteAccountPeersItemNodeTransition] = [] + + var tag: ItemListItemTag? { + return self.item?.tag + } + + init() { + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.topStripeNode = ASDisplayNode() + self.topStripeNode.isLayerBacked = true + + self.bottomStripeNode = ASDisplayNode() + self.bottomStripeNode.isLayerBacked = true + + self.maskNode = ASImageNode() + self.maskNode.isUserInteractionEnabled = false + + self.listView = ListView() + self.listView.transform = CATransform3DMakeRotation(-CGFloat.pi / 2.0, 0.0, 0.0, 1.0) + + super.init(layerBacked: false, dynamicBounce: false) + + self.addSubnode(self.listView) + + let previous: Atomic<[PeersEntry]> = Atomic(value: []) + let firstTime:Atomic = Atomic(value: true) + + self.disposable = (self.dataPromise.get() |> deliverOnMainQueue).start(next: { [weak self] data in + if let strongSelf = self { + let (context, peers, theme, strings) = data + + var entries: [PeersEntry] = [] + for peer in peers { + entries.append(PeersEntry(index: entries.count, peer: peer, theme: theme, strings: strings)) + } + + let animated = !firstTime.swap(false) + + let transition = preparedPeersTransition(context: context, from: previous.swap(entries), to: entries, firstTime: !animated, animated: animated) + strongSelf.enqueueTransition(transition) + } + }) + } + + deinit { + self.disposable?.dispose() + } + + private func enqueueTransition(_ transition: DeleteAccountPeersItemNodeTransition) { + self.queuedTransitions.append(transition) + self.dequeueTransitions() + } + + private func dequeueTransitions() { + while !self.queuedTransitions.isEmpty { + let transition = self.queuedTransitions.removeFirst() + + var options = ListViewDeleteAndInsertOptions() + if transition.firstTime { + options.insert(.PreferSynchronousResourceLoading) + options.insert(.PreferSynchronousDrawing) + options.insert(.Synchronous) + options.insert(.LowLatency) + } else if transition.animated { + options.insert(.AnimateInsertion) + } + self.listView.transaction(deleteIndices: transition.deletions, insertIndicesAndItems: transition.insertions, updateIndicesAndItems: transition.updates, options: options, updateOpaqueState: nil, completion: { _ in }) + } + } + + func asyncLayout() -> (_ item: DeleteAccountPeersItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { + let currentItem = self.item + + return { item, params, neighbors in + var themeUpdated = false + if currentItem?.theme !== item.theme { + themeUpdated = true + } + print(themeUpdated) + + let contentSize: CGSize + var insets: UIEdgeInsets + let separatorHeight = UIScreenPixel + + contentSize = CGSize(width: params.width, height: 109.0) + insets = itemListNeighborsGroupedInsets(neighbors, params) + + let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) + let layoutSize = layout.size + + return (layout, { [weak self] in + if let strongSelf = self { + strongSelf.item = item + strongSelf.layoutParams = params + + strongSelf.dataPromise.set(.single((item.context, item.peers, item.theme, item.strings))) + + strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor + strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + + if strongSelf.backgroundNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) + } + if strongSelf.topStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1) + } + if strongSelf.bottomStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) + } + if strongSelf.maskNode.supernode == nil { + strongSelf.addSubnode(strongSelf.maskNode) + } + + let hasCorners = itemListHasRoundedBlockLayout(params) + var hasTopCorners = false + var hasBottomCorners = false + switch neighbors.top { + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners + } + let bottomStripeInset: CGFloat + let bottomStripeOffset: CGFloat + switch neighbors.bottom { + case .sameSection(false): + bottomStripeInset = params.leftInset + 16.0 + bottomStripeOffset = -separatorHeight + strongSelf.bottomStripeNode.isHidden = false + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners + } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) + strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) + strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) + + let listInsets = UIEdgeInsets(top: params.leftInset, left: 0.0, bottom: params.rightInset, right: 0.0) + strongSelf.listView.bounds = CGRect(x: 0.0, y: 0.0, width: 92.0, height: params.width) + strongSelf.listView.position = CGPoint(x: params.width / 2.0, y: contentSize.height / 2.0) + strongSelf.listView.transaction(deleteIndices: [], insertIndicesAndItems: [], updateIndicesAndItems: [], options: [.Synchronous], scrollToItem: nil, updateSizeAndInsets: ListViewUpdateSizeAndInsets(size: CGSize(width: 92.0, height: params.width), insets: listInsets, duration: 0.0, curve: .Default(duration: nil)), stationaryItemRange: nil, updateOpaqueState: nil, completion: { _ in }) + + strongSelf.dequeueTransitions() + } + }) + } + } + + override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4) + } + + override func animateRemoved(_ currentTimestamp: Double, duration: Double) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) + } +} diff --git a/submodules/SettingsUI/Sources/DeleteAccountPhoneItem.swift b/submodules/SettingsUI/Sources/DeleteAccountPhoneItem.swift new file mode 100644 index 0000000000..a36fbca9a2 --- /dev/null +++ b/submodules/SettingsUI/Sources/DeleteAccountPhoneItem.swift @@ -0,0 +1,413 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import SwiftSignalKit +import TelegramCore +import TelegramPresentationData +import TelegramUIPreferences +import ItemListUI +import PresentationDataUtils +import PhoneInputNode +import CountrySelectionUI +import CoreTelephony + +private func generateCountryButtonBackground(color: UIColor, strokeColor: UIColor) -> UIImage? { + return generateImage(CGSize(width: 56, height: 44.0 + 6.0), rotatedContext: { size, context in + let arrowSize: CGFloat = 6.0 + let lineWidth = UIScreenPixel + + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(color.cgColor) + context.fill(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height - arrowSize))) + context.move(to: CGPoint(x: size.width, y: size.height - arrowSize)) + context.addLine(to: CGPoint(x: size.width - 1.0, y: size.height - arrowSize)) + context.addLine(to: CGPoint(x: size.width - 1.0 - arrowSize, y: size.height)) + context.addLine(to: CGPoint(x: size.width - 1.0 - arrowSize - arrowSize, y: size.height - arrowSize)) + context.closePath() + context.fillPath() + + context.setStrokeColor(strokeColor.cgColor) + context.setLineWidth(lineWidth) + + context.move(to: CGPoint(x: size.width, y: size.height - arrowSize - lineWidth / 2.0)) + context.addLine(to: CGPoint(x: size.width - 1.0, y: size.height - arrowSize - lineWidth / 2.0)) + context.addLine(to: CGPoint(x: size.width - 1.0 - arrowSize, y: size.height - lineWidth / 2.0)) + context.addLine(to: CGPoint(x: size.width - 1.0 - arrowSize - arrowSize, y: size.height - arrowSize - lineWidth / 2.0)) + context.addLine(to: CGPoint(x: 15.0, y: size.height - arrowSize - lineWidth / 2.0)) + context.strokePath() + + context.move(to: CGPoint(x: 0.0, y: lineWidth / 2.0)) + context.addLine(to: CGPoint(x: size.width, y: lineWidth / 2.0)) + context.strokePath() + })?.stretchableImage(withLeftCapWidth: 55, topCapHeight: 1) +} + +private func generateCountryButtonHighlightedBackground(color: UIColor) -> UIImage? { + return generateImage(CGSize(width: 56.0, height: 44.0 + 6.0), rotatedContext: { size, context in + let arrowSize: CGFloat = 6.0 + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(color.cgColor) + context.fill(CGRect(origin: CGPoint(), size: CGSize(width: size.width, height: size.height - arrowSize))) + context.move(to: CGPoint(x: size.width, y: size.height - arrowSize)) + context.addLine(to: CGPoint(x: size.width - 1.0, y: size.height - arrowSize)) + context.addLine(to: CGPoint(x: size.width - 1.0 - arrowSize, y: size.height)) + context.addLine(to: CGPoint(x: size.width - 1.0 - arrowSize - arrowSize, y: size.height - arrowSize)) + context.closePath() + context.fillPath() + })?.stretchableImage(withLeftCapWidth: 55, topCapHeight: 2) +} + +private func generatePhoneInputBackground(color: UIColor, strokeColor: UIColor) -> UIImage? { + return generateImage(CGSize(width: 82.0, height: 44.0), rotatedContext: { size, context in + let lineWidth = UIScreenPixel + context.clear(CGRect(origin: CGPoint(), size: size)) + context.setFillColor(color.cgColor) + context.fill(CGRect(origin: CGPoint(), size: size)) + context.setStrokeColor(strokeColor.cgColor) + context.setLineWidth(lineWidth) + context.move(to: CGPoint(x: 0.0, y: size.height - lineWidth / 2.0)) + context.addLine(to: CGPoint(x: size.width, y: size.height - lineWidth / 2.0)) + context.strokePath() + context.move(to: CGPoint(x: size.width - 2.0 + lineWidth / 2.0, y: size.height - lineWidth / 2.0)) + context.addLine(to: CGPoint(x: size.width - 2.0 + lineWidth / 2.0, y: 0.0)) + context.strokePath() + })?.stretchableImage(withLeftCapWidth: 81, topCapHeight: 2) +} + + +class DeleteAccountPhoneItem: ListViewItem, ItemListItem { + let theme: PresentationTheme + let strings: PresentationStrings + let value: (Int32?, String?, String) + let sectionId: ItemListSectionId + let selectCountryCode: () -> Void + let updated: (Int) -> Void + + init(theme: PresentationTheme, strings: PresentationStrings, value: (Int32?, String?, String), sectionId: ItemListSectionId, selectCountryCode: @escaping () -> Void, updated: @escaping (Int) -> Void) { + self.theme = theme + self.strings = strings + self.value = value + self.sectionId = sectionId + self.selectCountryCode = selectCountryCode + self.updated = updated + } + + func nodeConfiguredForParams(async: @escaping (@escaping () -> Void) -> Void, params: ListViewItemLayoutParams, synchronousLoads: Bool, previousItem: ListViewItem?, nextItem: ListViewItem?, completion: @escaping (ListViewItemNode, @escaping () -> (Signal?, (ListViewItemApply) -> Void)) -> Void) { + async { + let node = DeleteAccountPhoneItemNode() + let (layout, apply) = node.asyncLayout()(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + + node.contentSize = layout.contentSize + node.insets = layout.insets + + Queue.mainQueue().async { + completion(node, { + return (nil, { _ in apply() }) + }) + } + } + } + + func updateNode(async: @escaping (@escaping () -> Void) -> Void, node: @escaping () -> ListViewItemNode, params: ListViewItemLayoutParams, previousItem: ListViewItem?, nextItem: ListViewItem?, animation: ListViewItemUpdateAnimation, completion: @escaping (ListViewItemNodeLayout, @escaping (ListViewItemApply) -> Void) -> Void) { + Queue.mainQueue().async { + if let nodeValue = node() as? DeleteAccountPhoneItemNode { + let makeLayout = nodeValue.asyncLayout() + + async { + let (layout, apply) = makeLayout(self, params, itemListNeighbors(item: self, topItem: previousItem as? ItemListItem, bottomItem: nextItem as? ItemListItem)) + Queue.mainQueue().async { + completion(layout, { _ in + apply() + }) + } + } + } + } + } +} + +class DeleteAccountPhoneItemNode: ListViewItemNode, ItemListItemNode { + private let backgroundNode: ASDisplayNode + private let topStripeNode: ASDisplayNode + private let bottomStripeNode: ASDisplayNode + private let maskNode: ASImageNode + + private let countryButton: ASButtonNode + private let phoneBackground: ASImageNode + private let phoneInputNode: PhoneInputNode + + private var item: DeleteAccountPhoneItem? + private var layoutParams: ListViewItemLayoutParams? + + var preferredCountryIdForCode: [String: String] = [:] + + var tag: ItemListItemTag? { + return self.item?.tag + } + + init() { + self.backgroundNode = ASDisplayNode() + self.backgroundNode.isLayerBacked = true + + self.topStripeNode = ASDisplayNode() + self.topStripeNode.isLayerBacked = true + + self.bottomStripeNode = ASDisplayNode() + self.bottomStripeNode.isLayerBacked = true + + self.maskNode = ASImageNode() + self.maskNode.isUserInteractionEnabled = false + + self.countryButton = ASButtonNode() + + self.phoneBackground = ASImageNode() + self.phoneBackground.displaysAsynchronously = false + self.phoneBackground.displayWithoutProcessing = true + self.phoneBackground.isLayerBacked = true + + self.phoneInputNode = PhoneInputNode(fontSize: 17.0) + + super.init(layerBacked: false, dynamicBounce: false) + + self.addSubnode(self.phoneBackground) + self.addSubnode(self.countryButton) + self.addSubnode(self.phoneInputNode) + + self.countryButton.contentEdgeInsets = UIEdgeInsets(top: 0.0, left: 15.0, bottom: 4.0, right: 0.0) + self.countryButton.contentHorizontalAlignment = .left + + self.countryButton.addTarget(self, action: #selector(self.countryPressed), forControlEvents: .touchUpInside) + + let processNumberChange: (String) -> Bool = { [weak self] number in + guard let strongSelf = self, let item = strongSelf.item else { + return false + } + if let (country, _) = AuthorizationSequenceCountrySelectionController.lookupCountryIdByNumber(number, preferredCountries: strongSelf.preferredCountryIdForCode) { + let flagString = emojiFlagForISOCountryCode(country.id) + let localizedName: String = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(country.id, strings: item.strings) ?? country.name + strongSelf.countryButton.setTitle("\(flagString) \(localizedName)", with: Font.regular(17.0), with: item.theme.list.itemPrimaryTextColor, for: []) + + let maskFont = Font.with(size: 20.0, design: .regular, traits: [.monospacedNumbers]) + if let mask = AuthorizationSequenceCountrySelectionController.lookupPatternByNumber(number, preferredCountries: strongSelf.preferredCountryIdForCode).flatMap({ NSAttributedString(string: $0, font: maskFont, textColor: item.theme.list.itemPlaceholderTextColor) }) { + strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = nil + strongSelf.phoneInputNode.mask = mask + } else { + strongSelf.phoneInputNode.mask = nil + strongSelf.phoneInputNode.numberField.textField.attributedPlaceholder = NSAttributedString(string: item.strings.Login_PhonePlaceholder, font: Font.regular(20.0), textColor: item.theme.list.itemPlaceholderTextColor) + } + return true + } else { + return false + } + } + + self.phoneInputNode.numberTextUpdated = { [weak self] number in + if let strongSelf = self { + let _ = processNumberChange(strongSelf.phoneInputNode.number) + } + } + + self.phoneInputNode.countryCodeUpdated = { [weak self] code, name in + if let strongSelf = self, let item = strongSelf.item { + if let name = name { + strongSelf.preferredCountryIdForCode[code] = name + } + + if processNumberChange(strongSelf.phoneInputNode.number) { + } else if let code = Int(code), let name = name, let countryName = countryCodeAndIdToName[CountryCodeAndId(code: code, id: name)] { + let localizedName: String = AuthorizationSequenceCountrySelectionController.lookupCountryNameById(name, strings: item.strings) ?? countryName + strongSelf.countryButton.setTitle(localizedName, with: Font.regular(17.0), with: item.theme.list.itemPrimaryTextColor, for: []) + } else if let code = Int(code), let (_, countryName) = countryCodeToIdAndName[code] { + strongSelf.countryButton.setTitle(countryName, with: Font.regular(17.0), with: item.theme.list.itemPrimaryTextColor, for: []) + } else { + strongSelf.countryButton.setTitle(item.strings.Login_CountryCode, with: Font.regular(17.0), with: item.theme.list.itemPrimaryTextColor, for: []) + } + } + } + + self.phoneInputNode.customFormatter = { number in + if let (_, code) = AuthorizationSequenceCountrySelectionController.lookupCountryIdByNumber(number, preferredCountries: [:]) { + return code.code + } else { + return nil + } + } + + var countryId: String? = nil + let networkInfo = CTTelephonyNetworkInfo() + if let carrier = networkInfo.subscriberCellularProvider { + countryId = carrier.isoCountryCode + } + + if countryId == nil { + countryId = (Locale.current as NSLocale).object(forKey: .countryCode) as? String + } + + var countryCodeAndId: (Int32, String) = (1, "US") + + if let countryId = countryId { + let normalizedId = countryId.uppercased() + for (code, idAndName) in countryCodeToIdAndName { + if idAndName.0 == normalizedId { + countryCodeAndId = (Int32(code), idAndName.0.uppercased()) + break + } + } + } + + self.phoneInputNode.number = "+\(countryCodeAndId.0)" + } + + @objc private func countryPressed() { + if let item = self.item { + item.selectCountryCode() + } + } + + var phoneNumber: String { + return self.phoneInputNode.number + } + + func updateCountryCode() { + self.phoneInputNode.codeAndNumber = self.phoneInputNode.codeAndNumber + } + + func updateCountryCode(code: Int32, name: String) { + self.phoneInputNode.codeAndNumber = (code, name, self.phoneInputNode.codeAndNumber.2) + } + + func activateInput() { + self.phoneInputNode.numberField.textField.becomeFirstResponder() + } + + func animateError() { + self.phoneInputNode.countryCodeField.layer.addShakeAnimation() + self.phoneInputNode.numberField.layer.addShakeAnimation() + } + + func asyncLayout() -> (_ item: DeleteAccountPhoneItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { + let currentItem = self.item + + return { item, params, neighbors in + var updatedCountryButtonBackground: UIImage? + var updatedCountryButtonHighlightedBackground: UIImage? + var updatedPhoneBackground: UIImage? + + if currentItem?.theme !== item.theme { + updatedCountryButtonBackground = generateCountryButtonBackground(color: item.theme.list.itemBlocksBackgroundColor, strokeColor: item.theme.list.itemBlocksSeparatorColor) + updatedCountryButtonHighlightedBackground = generateCountryButtonHighlightedBackground(color: item.theme.list.itemHighlightedBackgroundColor) + updatedPhoneBackground = generatePhoneInputBackground(color: item.theme.list.itemBlocksBackgroundColor, strokeColor: item.theme.list.itemBlocksSeparatorColor) + } + + let contentSize: CGSize + var insets: UIEdgeInsets + let separatorHeight = UIScreenPixel + + let countryButtonHeight: CGFloat = 44.0 + let inputFieldsHeight: CGFloat = 44.0 + + contentSize = CGSize(width: params.width, height: countryButtonHeight + inputFieldsHeight) + insets = itemListNeighborsGroupedInsets(neighbors, params) + + let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) + let layoutSize = layout.size + + return (layout, { [weak self] in + if let strongSelf = self { + strongSelf.item = item + strongSelf.layoutParams = params + + strongSelf.backgroundNode.backgroundColor = item.theme.list.itemBlocksBackgroundColor + strongSelf.topStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + strongSelf.bottomStripeNode.backgroundColor = item.theme.list.itemBlocksSeparatorColor + + if strongSelf.backgroundNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.backgroundNode, at: 0) + } + if strongSelf.topStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.topStripeNode, at: 1) + } + if strongSelf.bottomStripeNode.supernode == nil { + strongSelf.insertSubnode(strongSelf.bottomStripeNode, at: 2) + } + if strongSelf.maskNode.supernode == nil { + strongSelf.addSubnode(strongSelf.maskNode) + } + + let hasCorners = itemListHasRoundedBlockLayout(params) + var hasTopCorners = false + var hasBottomCorners = false + switch neighbors.top { + case .sameSection(false): + strongSelf.topStripeNode.isHidden = true + default: + hasTopCorners = true + strongSelf.topStripeNode.isHidden = hasCorners + } + let bottomStripeInset: CGFloat + let bottomStripeOffset: CGFloat + switch neighbors.bottom { + case .sameSection(false): + bottomStripeInset = params.leftInset + 16.0 + bottomStripeOffset = -separatorHeight + strongSelf.bottomStripeNode.isHidden = false + default: + bottomStripeInset = 0.0 + bottomStripeOffset = 0.0 + hasBottomCorners = true + strongSelf.bottomStripeNode.isHidden = hasCorners + } + + strongSelf.maskNode.image = hasCorners ? PresentationResourcesItemList.cornersImage(item.theme, top: hasTopCorners, bottom: hasBottomCorners) : nil + + strongSelf.backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: params.width, height: contentSize.height + min(insets.top, separatorHeight) + min(insets.bottom, separatorHeight))) + strongSelf.maskNode.frame = strongSelf.backgroundNode.frame.insetBy(dx: params.leftInset, dy: 0.0) + strongSelf.topStripeNode.frame = CGRect(origin: CGPoint(x: 0.0, y: -min(insets.top, separatorHeight)), size: CGSize(width: layoutSize.width, height: separatorHeight)) + strongSelf.bottomStripeNode.frame = CGRect(origin: CGPoint(x: bottomStripeInset, y: contentSize.height + bottomStripeOffset), size: CGSize(width: layoutSize.width - bottomStripeInset, height: separatorHeight)) + + if let updatedCountryButtonBackground = updatedCountryButtonBackground { + strongSelf.countryButton.setBackgroundImage(updatedCountryButtonBackground, for: []) + } + if let updatedCountryButtonHighlightedBackground = updatedCountryButtonHighlightedBackground { + strongSelf.countryButton.setBackgroundImage(updatedCountryButtonHighlightedBackground, for: .highlighted) + } + if let updatedPhoneBackground = updatedPhoneBackground { + strongSelf.phoneBackground.image = updatedPhoneBackground + } + + strongSelf.phoneInputNode.countryCodeField.textField.textColor = item.theme.list.itemPrimaryTextColor + strongSelf.phoneInputNode.countryCodeField.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance + strongSelf.phoneInputNode.countryCodeField.textField.tintColor = item.theme.list.itemAccentColor + strongSelf.phoneInputNode.numberField.textField.textColor = item.theme.list.itemPrimaryTextColor + strongSelf.phoneInputNode.numberField.textField.keyboardAppearance = item.theme.rootController.keyboardColor.keyboardAppearance + strongSelf.phoneInputNode.numberField.textField.tintColor = item.theme.list.itemAccentColor + + strongSelf.countryButton.contentEdgeInsets = UIEdgeInsets(top: 0.0, left: params.leftInset + 15.0, bottom: 4.0, right: 0.0) + + strongSelf.countryButton.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: params.width, height: 44.0 + 6.0)) + strongSelf.phoneBackground.frame = CGRect(origin: CGPoint(x: 0.0, y: 44.0), size: CGSize(width: params.width, height: 44.0)) + + let countryCodeFrame = CGRect(origin: CGPoint(x: 11.0, y: 44.0), size: CGSize(width: 67.0, height: 44.0)) + let numberFrame = CGRect(origin: CGPoint(x: 92.0, y: 44.0), size: CGSize(width: layout.size.width - 70.0 - 8.0, height: 44.0)) + let placeholderFrame = numberFrame.offsetBy(dx: 0.0, dy: 8.0) + + let phoneInputFrame = countryCodeFrame.union(numberFrame) + + strongSelf.phoneInputNode.frame = phoneInputFrame + strongSelf.phoneInputNode.countryCodeField.frame = countryCodeFrame.offsetBy(dx: -phoneInputFrame.minX, dy: -phoneInputFrame.minY) + strongSelf.phoneInputNode.numberField.frame = numberFrame.offsetBy(dx: -phoneInputFrame.minX, dy: -phoneInputFrame.minY) + strongSelf.phoneInputNode.placeholderNode.frame = placeholderFrame.offsetBy(dx: -phoneInputFrame.minX, dy: -phoneInputFrame.minY) + } + }) + } + } + + override func animateInsertion(_ currentTimestamp: Double, duration: Double, short: Bool) { + self.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.4) + } + + override func animateRemoved(_ currentTimestamp: Double, duration: Double) { + self.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) + } +} diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index f594a23db5..7a070c170a 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -482,6 +482,10 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD return entries } +class PrivacyAndSecurityControllerImpl: ItemListController { + +} + public func privacyAndSecurityController(context: AccountContext, initialSettings: AccountPrivacySettings? = nil, updatedSettings: ((AccountPrivacySettings?) -> Void)? = nil, updatedBlockedPeers: ((BlockedPeersContext?) -> Void)? = nil, updatedHasTwoStepAuth: ((Bool) -> Void)? = nil, focusOnItemTag: PrivacyAndSecurityEntryTag? = nil, activeSessionsContext: ActiveSessionsContext? = nil, webSessionsContext: WebSessionsContext? = nil, blockedPeersContext: BlockedPeersContext? = nil, hasTwoStepAuth: Bool? = nil) -> ViewController { let statePromise = ValuePromise(PrivacyAndSecurityControllerState(), ignoreRepeated: true) let stateValue = Atomic(value: PrivacyAndSecurityControllerState()) @@ -492,6 +496,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting var pushControllerImpl: ((ViewController, Bool) -> Void)? var replaceTopControllerImpl: ((ViewController) -> Void)? var presentControllerImpl: ((ViewController) -> Void)? + var getNavigationControllerImpl: (() -> NavigationController?)? let actionsDisposable = DisposableSet() @@ -822,12 +827,26 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting 6 * 30 * 24 * 60 * 60, 365 * 24 * 60 * 60 ] - let timeoutItems: [ActionSheetItem] = timeoutValues.map { value in + var timeoutItems: [ActionSheetItem] = timeoutValues.map { value in return ActionSheetButtonItem(title: timeIntervalString(strings: presentationData.strings, value: value), action: { dismissAction() timeoutAction(value) }) } + timeoutItems.append(ActionSheetButtonItem(title: presentationData.strings.PrivacySettings_DeleteAccountNow, color: .destructive, action: { + dismissAction() + + guard let navigationController = getNavigationControllerImpl?() else { + return + } + + let _ = (combineLatest(twoStepAuth.get(), twoStepAuthDataValue.get()) + |> take(1) + |> deliverOnMainQueue).start(next: { hasTwoStepAuth, twoStepAuthData in + let optionsController = deleteAccountOptionsController(context: context, navigationController: navigationController, hasTwoStepAuth: hasTwoStepAuth ?? false, twoStepAuthData: twoStepAuthData) + pushControllerImpl?(optionsController, true) + }) + })) controller.setItemGroups([ ActionSheetItemGroup(items: timeoutItems), ActionSheetItemGroup(items: [ActionSheetButtonItem(title: presentationData.strings.Common_Cancel, action: { dismissAction() })]) @@ -886,7 +905,7 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting actionsDisposable.dispose() } - let controller = ItemListController(context: context, state: signal) + let controller = PrivacyAndSecurityControllerImpl(context: context, state: signal) pushControllerImpl = { [weak controller] c, animated in (controller?.navigationController as? NavigationController)?.pushViewController(c, animated: animated) } @@ -896,7 +915,10 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting presentControllerImpl = { [weak controller] c in controller?.present(c, in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet)) } - + getNavigationControllerImpl = { [weak controller] in + return (controller?.navigationController as? NavigationController) + } + controller.didAppear = { _ in updateHasTwoStepAuth() } diff --git a/submodules/SettingsUI/Sources/Privacy and Security/TwoStepVerificationUnlockController.swift b/submodules/SettingsUI/Sources/Privacy and Security/TwoStepVerificationUnlockController.swift index 4ab4a52ad1..2d53114931 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/TwoStepVerificationUnlockController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/TwoStepVerificationUnlockController.swift @@ -206,7 +206,7 @@ private func twoStepVerificationUnlockSettingsControllerEntries(presentationData if let pendingEmail = pendingEmail { entries.append(.pendingEmailConfirmInfo(presentationData.theme, presentationData.strings.TwoStepAuth_SetupPendingEmail(pendingEmail.email.pattern).string)) entries.append(.pendingEmailConfirmCode(presentationData.theme, presentationData.strings, presentationData.strings.TwoStepAuth_RecoveryCode, state.emailCode)) - entries.append(.pendingEmailInfo(presentationData.theme, "[" + presentationData.strings.TwoStepAuth_ConfirmationAbort + "]()")) + entries.append(.pendingEmailInfo(presentationData.theme, "[" + presentationData.strings.TwoStepAuth_ConfirmationAbort + "]()")) /*entries.append(.pendingEmailInfo(presentationData.theme, presentationData.strings.TwoStepAuth_ConfirmationText + "\n\n\(pendingEmailAndValue.pendingEmail.pattern)\n\n[" + presentationData.strings.TwoStepAuth_ConfirmationAbort + "]()"))*/ } else { diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift index 6731dbcd62..5910683d1f 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift @@ -91,6 +91,7 @@ public struct PresentationResourcesSettings { public static let changePhoneNumber = renderIcon(name: "Settings/Menu/ChangePhoneNumber") public static let deleteAddAccount = renderIcon(name: "Settings/Menu/DeleteAddAccount") + public static let deleteSetTwoStepAuth = renderIcon(name: "Settings/Menu/DeleteTwoStepAuth") public static let deleteSetPasscode = renderIcon(name: "Settings/Menu/FaceId") public static let deleteChats = renderIcon(name: "Settings/Menu/DeleteChats") public static let clearSynced = renderIcon(name: "Settings/Menu/ClearSynced") diff --git a/submodules/TelegramUI/Images.xcassets/Components/BadgeTEst.imageset/AppBadge@3x.png b/submodules/TelegramUI/Images.xcassets/Components/AppBadge.imageset/AppBadge@3x.png similarity index 100% rename from submodules/TelegramUI/Images.xcassets/Components/BadgeTEst.imageset/AppBadge@3x.png rename to submodules/TelegramUI/Images.xcassets/Components/AppBadge.imageset/AppBadge@3x.png diff --git a/submodules/TelegramUI/Images.xcassets/Components/BadgeTEst.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Components/AppBadge.imageset/Contents.json similarity index 100% rename from submodules/TelegramUI/Images.xcassets/Components/BadgeTEst.imageset/Contents.json rename to submodules/TelegramUI/Images.xcassets/Components/AppBadge.imageset/Contents.json diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Contents.json new file mode 100644 index 0000000000..bfbeb098c2 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "Icon.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Icon.pdf b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Icon.pdf new file mode 100644 index 0000000000..d771d5afaf --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Settings/Menu/DeleteTwoStepAuth.imageset/Icon.pdf @@ -0,0 +1,114 @@ +%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 0.000000 0.000000 cm +0.345098 0.337255 0.839216 scn +0.000000 18.799999 m +0.000000 22.720367 0.000000 24.680552 0.762954 26.177933 c +1.434068 27.495068 2.504932 28.565931 3.822066 29.237045 c +5.319448 30.000000 7.279633 30.000000 11.200000 30.000000 c +18.799999 30.000000 l +22.720367 30.000000 24.680552 30.000000 26.177933 29.237045 c +27.495068 28.565931 28.565931 27.495068 29.237045 26.177933 c +30.000000 24.680552 30.000000 22.720367 30.000000 18.799999 c +30.000000 11.200001 l +30.000000 7.279633 30.000000 5.319448 29.237045 3.822067 c +28.565931 2.504932 27.495068 1.434069 26.177933 0.762955 c +24.680552 0.000000 22.720367 0.000000 18.799999 0.000000 c +11.200000 0.000000 l +7.279633 0.000000 5.319448 0.000000 3.822066 0.762955 c +2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c +0.000000 5.319448 0.000000 7.279633 0.000000 11.200001 c +0.000000 18.799999 l +h +f +n +Q +q +-1.000000 -0.000000 -0.000000 1.000000 25.000000 6.000000 cm +1.000000 1.000000 1.000000 scn +6.650000 19.000000 m +2.945000 19.000000 0.000000 16.055000 0.000000 12.350000 c +0.000000 8.645000 2.945000 5.700001 6.650000 5.700001 c +7.500165 5.700001 8.310955 5.861581 9.054688 6.145313 c +10.450001 4.750000 l +12.350000 4.750000 l +12.350000 2.850000 l +14.250000 2.850000 l +14.250000 0.950001 l +14.903126 0.296875 l +15.093125 0.106874 15.300938 0.000000 15.585938 0.000000 c +18.049999 0.000000 l +18.619999 0.000000 19.000000 0.380001 19.000000 0.950001 c +19.000000 3.414062 l +19.000000 3.699062 18.893126 3.906875 18.703125 4.096874 c +12.854687 9.945312 l +13.138419 10.689045 13.299999 11.499835 13.299999 12.350000 c +13.299999 16.055000 10.355000 19.000000 6.650000 19.000000 c +h +5.225000 16.150000 m +6.555000 16.150000 7.600000 15.105000 7.600000 13.775000 c +7.600000 12.445000 6.555000 11.400000 5.225000 11.400000 c +3.895000 11.400000 2.850000 12.445000 2.850000 13.775000 c +2.850000 15.105000 3.895000 16.150000 5.225000 16.150000 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1987 +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 +0000002077 00000 n +0000002100 00000 n +0000002273 00000 n +0000002347 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2406 +%%EOF \ No newline at end of file From 7868651acb93f040a55e78567497bf2c8bc50b3f Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Tue, 28 Jun 2022 23:32:27 +0300 Subject: [PATCH 017/113] Various fixes --- submodules/TabBarUI/Sources/TabBarNode.swift | 14 +++++++++----- .../Tabs/IconSettings.imageset/Contents.json | 13 ++++++++----- .../Sources/PeerInfo/PeerInfoScreen.swift | 10 +++++----- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/submodules/TabBarUI/Sources/TabBarNode.swift b/submodules/TabBarUI/Sources/TabBarNode.swift index 86ebf72173..0cb0a35bf4 100644 --- a/submodules/TabBarUI/Sources/TabBarNode.swift +++ b/submodules/TabBarUI/Sources/TabBarNode.swift @@ -317,6 +317,8 @@ class TabBarNode: ASDisplayNode { } } + var reduceMotion: Bool = false + var selectedIndex: Int? { didSet { if self.selectedIndex != oldValue { @@ -574,12 +576,14 @@ class TabBarNode: ASDisplayNode { node.contentWidth = max(contentWidth, imageContentWidth) node.isSelected = true - ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut).updateTransformScale(node: node.ringImageNode, scale: 1.0, delay: 0.1) - node.imageNode.layer.animateScale(from: 1.0, to: 0.87, duration: 0.1, removeOnCompletion: false, completion: { [weak node] _ in - node?.imageNode.layer.animateScale(from: 0.87, to: 1.0, duration: 0.14, removeOnCompletion: false, completion: { [weak node] _ in - node?.imageNode.layer.removeAllAnimations() + if !self.reduceMotion && item.item.ringSelection { + ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut).updateTransformScale(node: node.ringImageNode, scale: 1.0, delay: 0.1) + node.imageNode.layer.animateScale(from: 1.0, to: 0.87, duration: 0.1, removeOnCompletion: false, completion: { [weak node] _ in + node?.imageNode.layer.animateScale(from: 0.87, to: 1.0, duration: 0.14, removeOnCompletion: false, completion: { [weak node] _ in + node?.imageNode.layer.removeAllAnimations() + }) }) - }) + } } else { let (textImage, contentWidth) = tabBarItemImage(item.item.image, title: item.item.title ?? "", backgroundColor: .clear, tintColor: self.theme.tabBarTextColor, horizontal: self.horizontal, imageMode: false, centered: self.centered) diff --git a/submodules/TelegramUI/Images.xcassets/Chat List/Tabs/IconSettings.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat List/Tabs/IconSettings.imageset/Contents.json index c457392e9f..4163ba603b 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat List/Tabs/IconSettings.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat List/Tabs/IconSettings.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "idiom" : "universal", - "filename" : "ic_tb_settings.pdf" + "filename" : "ic_tb_settings.pdf", + "idiom" : "universal" } ], "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" } -} \ No newline at end of file +} diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index ccc3a9f4c8..4fe61f6e60 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -7990,8 +7990,8 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen { icon = UIImage(bundleImageName: "Chat List/Tabs/IconSettings") } - let tabBarItem: Signal<(String, UIImage?, UIImage?, String?, Bool), NoError> = combineLatest(queue: .mainQueue(), self.context.sharedContext.presentationData, notificationsAuthorizationStatus.get(), notificationsWarningSuppressed.get(), getServerProvidedSuggestions(account: self.context.account), accountTabBarAvatar, accountTabBarAvatarBadge) - |> map { presentationData, notificationsAuthorizationStatus, notificationsWarningSuppressed, suggestions, accountTabBarAvatar, accountTabBarAvatarBadge -> (String, UIImage?, UIImage?, String?, Bool) in + let tabBarItem: Signal<(String, UIImage?, UIImage?, String?, Bool, Bool), NoError> = combineLatest(queue: .mainQueue(), self.context.sharedContext.presentationData, notificationsAuthorizationStatus.get(), notificationsWarningSuppressed.get(), getServerProvidedSuggestions(account: self.context.account), accountTabBarAvatar, accountTabBarAvatarBadge) + |> map { presentationData, notificationsAuthorizationStatus, notificationsWarningSuppressed, suggestions, accountTabBarAvatar, accountTabBarAvatarBadge -> (String, UIImage?, UIImage?, String?, Bool, Bool) in let notificationsWarning = shouldDisplayNotificationsPermissionWarning(status: notificationsAuthorizationStatus, suppressed: notificationsWarningSuppressed) let phoneNumberWarning = suggestions.contains(.validatePhoneNumber) let passwordWarning = suggestions.contains(.validatePassword) @@ -7999,15 +7999,15 @@ public final class PeerInfoScreenImpl: ViewController, PeerInfoScreen { if accountTabBarAvatarBadge > 0 { otherAccountsBadge = compactNumericCountString(Int(accountTabBarAvatarBadge), decimalSeparator: presentationData.dateTimeFormat.decimalSeparator) } - return (presentationData.strings.Settings_Title, accountTabBarAvatar?.0 ?? icon, accountTabBarAvatar?.1 ?? icon, notificationsWarning || phoneNumberWarning || passwordWarning ? "!" : otherAccountsBadge, accountTabBarAvatar != nil || presentationData.reduceMotion) + return (presentationData.strings.Settings_Title, accountTabBarAvatar?.0 ?? icon, accountTabBarAvatar?.1 ?? icon, notificationsWarning || phoneNumberWarning || passwordWarning ? "!" : otherAccountsBadge, accountTabBarAvatar != nil, presentationData.reduceMotion) } - self.tabBarItemDisposable = (tabBarItem |> deliverOnMainQueue).start(next: { [weak self] title, image, selectedImage, badgeValue, isAvatar in + self.tabBarItemDisposable = (tabBarItem |> deliverOnMainQueue).start(next: { [weak self] title, image, selectedImage, badgeValue, isAvatar, reduceMotion in if let strongSelf = self { strongSelf.tabBarItem.title = title strongSelf.tabBarItem.image = image strongSelf.tabBarItem.selectedImage = selectedImage - strongSelf.tabBarItem.animationName = isAvatar ? nil : "TabSettings" + strongSelf.tabBarItem.animationName = isAvatar || reduceMotion ? nil : "TabSettings" strongSelf.tabBarItem.ringSelection = isAvatar strongSelf.tabBarItem.badgeValue = badgeValue } From 131be5aaab8c4614e8f5eb442c57d01f8bb77fb5 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 28 Jun 2022 22:54:05 +0200 Subject: [PATCH 018/113] Input node improvements --- .../Source/Base/Transition.swift | 3 + .../Sources/ComponentDisplayAdapters.swift | 16 +- .../Sources/PagerComponent.swift | 5 +- .../ContextUI/Sources/PeekController.swift | 10 +- .../PeekControllerGestureRecognizer.swift | 24 +- .../Source/ContextControllerSourceNode.swift | 53 +- .../Display/Source/ContextGesture.swift | 11 +- .../Navigation/NavigationController.swift | 2 +- .../Navigation/NavigationModalFrame.swift | 8 +- .../ImportStickerPackControllerNode.swift | 10 +- .../StickerPackPreviewControllerNode.swift | 12 +- .../Sources/StickerPackPreviewGridItem.swift | 2 +- .../Sources/StickerPackScreen.swift | 12 +- .../Sources/StickerPreviewPeekContent.swift | 6 +- submodules/TelegramUI/BUILD | 1 + .../Components/AnimationCache/BUILD | 2 +- .../DCT/PublicHeaders/DCT/DCT.h | 14 - .../AnimationCache/DCT/Sources/DCT.m | 991 ------------------ .../AnimationCache/{DCT => ImageDCT}/BUILD | 7 +- .../PublicHeaders/ImageDCT/ImageDCT.h | 17 + .../PublicHeaders/ImageDCT}/YuvConversion.h | 0 .../AnimationCache/ImageDCT/Sources/DCT.cpp | 376 +++++++ .../AnimationCache/ImageDCT/Sources/DCT.h | 26 + .../ImageDCT/Sources/DCTCommon.h | 27 + .../AnimationCache/ImageDCT/Sources/DCT_C.c | 399 +++++++ .../ImageDCT/Sources/DCT_Neon.c | 677 ++++++++++++ .../ImageDCT/Sources/ImageDCT.mm | 31 + .../{DCT => ImageDCT}/Sources/YuvConversion.m | 2 +- .../AnimationCache/Sources/ImageData.swift | 12 +- .../Components/ChatInputPanelContainer/BUILD | 20 + .../Sources/ChatInputPanelContainer.swift | 113 ++ .../Components/EntityKeyboard/BUILD | 5 + .../Sources/EmojiPagerContentComponent.swift | 267 ++++- .../Sources/EntityKeyboard.swift | 8 +- .../EntityKeyboardTopPanelComponent.swift | 5 +- .../TelegramUI/Sources/ChatController.swift | 24 +- .../Sources/ChatControllerNode.swift | 497 +++++---- .../Sources/ChatEntityKeyboardInputNode.swift | 101 +- .../TelegramUI/Sources/ChatInputNode.swift | 3 + .../Sources/ChatInterfaceInputNodes.swift | 2 +- .../Sources/ChatMediaInputNode.swift | 16 +- .../ChatMediaInputStickerGridItem.swift | 2 +- .../Sources/ChatMessageTransitionNode.swift | 10 +- .../Sources/ChatTextInputPanelNode.swift | 10 +- .../Sources/FeaturedStickersScreen.swift | 18 +- ...textResultsChatInputContextPanelNode.swift | 12 +- ...rizontalStickersChatContextPanelNode.swift | 24 +- .../Sources/InlineReactionSearchPanel.swift | 24 +- .../StickerPaneSearchContentNode.swift | 8 +- .../StickersChatInputContextPanelItem.swift | 2 +- .../StickersChatInputContextPanelNode.swift | 22 +- 51 files changed, 2586 insertions(+), 1363 deletions(-) delete mode 100644 submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h delete mode 100644 submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m rename submodules/TelegramUI/Components/AnimationCache/{DCT => ImageDCT}/BUILD (72%) create mode 100644 submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h rename submodules/TelegramUI/Components/AnimationCache/{DCT/PublicHeaders/DCT => ImageDCT/PublicHeaders/ImageDCT}/YuvConversion.h (100%) create mode 100644 submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp create mode 100644 submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h create mode 100644 submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCTCommon.h create mode 100644 submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_C.c create mode 100644 submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT_Neon.c create mode 100644 submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm rename submodules/TelegramUI/Components/AnimationCache/{DCT => ImageDCT}/Sources/YuvConversion.m (98%) create mode 100644 submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD create mode 100644 submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index 1477eb4fbd..a57d781e9d 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -120,6 +120,8 @@ 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() } @@ -131,6 +133,7 @@ public struct Transition { public enum Curve { case easeInOut case spring + case custom(Float, Float, Float, Float) } case none diff --git a/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift b/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift index 34fa9ce017..2c50f91083 100644 --- a/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift +++ b/submodules/Components/ComponentDisplayAdapters/Sources/ComponentDisplayAdapters.swift @@ -10,8 +10,8 @@ public extension Transition.Animation.Curve { self = .easeInOut case .easeInOut: self = .easeInOut - case .custom: - self = .spring + case let .custom(a, b, c, d): + self = .custom(a, b, c, d) case .customSpring: self = .spring case .spring: @@ -21,10 +21,12 @@ public extension Transition.Animation.Curve { var containedViewLayoutTransitionCurve: ContainedViewLayoutTransitionCurve { switch self { - case .easeInOut: - return .easeInOut - case .spring: - return .spring + case .easeInOut: + return .easeInOut + case .spring: + return .spring + case let .custom(a, b, c, d): + return .custom(a, b, c, d) } } } @@ -47,4 +49,4 @@ public extension Transition { return .animated(duration: duration, curve: curve.containedViewLayoutTransitionCurve) } } -} \ No newline at end of file +} diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index 12b311e547..c24f6a728b 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -532,14 +532,13 @@ public final class PagerComponent: Component { } var removedIds: [AnyHashable] = [] - for (id, contentView) in self.contentViews { + for (id, _) in self.contentViews { if !validIds.contains(id) { removedIds.append(id) - contentView.view.removeFromSuperview() } } for id in removedIds { - self.contentViews.removeValue(forKey: id) + self.contentViews.removeValue(forKey: id)?.view.removeFromSuperview() } if let panelStateUpdated = component.panelStateUpdated { diff --git a/submodules/ContextUI/Sources/PeekController.swift b/submodules/ContextUI/Sources/PeekController.swift index 78950898b7..2bacd9ad6f 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,10 @@ public final class PeekController: ViewController, ContextControllerProtocol { private var animatedIn = false - public init(presentationData: PresentationData, content: PeekControllerContent, sourceNode: @escaping () -> ASDisplayNode?) { + 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 +90,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/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/Display/Source/ContextControllerSourceNode.swift b/submodules/Display/Source/ContextControllerSourceNode.swift index 5429722f3b..3e2d8916c5 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 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..7a2a1b0de0 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 } } @@ -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/Navigation/NavigationController.swift b/submodules/Display/Source/Navigation/NavigationController.swift index eaacde87bd..c5679aabd9 100644 --- a/submodules/Display/Source/Navigation/NavigationController.swift +++ b/submodules/Display/Source/Navigation/NavigationController.swift @@ -938,7 +938,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 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/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift index 1bb571e473..5c991109d9 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 { diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index a317390966..68f071283e 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -197,7 +197,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 +212,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 { @@ -238,7 +238,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 +248,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 { diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift index 6009f7e493..a5dc7ae6d6 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift @@ -343,7 +343,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 7cb8c4b2b2..03355801aa 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -344,7 +344,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 +359,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 { @@ -385,7 +385,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 +401,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 { diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift b/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift index 96c61efd36..07dbc281d7 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift +++ b/submodules/StickerPackPreviewUI/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 } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index ccf6ae5604..c0eb480146 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -287,6 +287,7 @@ swift_library( "//submodules/TelegramUI/Components/LottieAnimationCache:LottieAnimationCache", "//submodules/TelegramUI/Components/VideoAnimationCache:VideoAnimationCache", "//submodules/TelegramUI/Components/MultiAnimationRenderer:MultiAnimationRenderer", + "//submodules/TelegramUI/Components/ChatInputPanelContainer:ChatInputPanelContainer", "//submodules/Components/ComponentDisplayAdapters:ComponentDisplayAdapters", "//submodules/Media/ConvertOpusToAAC:ConvertOpusToAAC", "//submodules/Media/LocalAudioTranscription:LocalAudioTranscription", diff --git a/submodules/TelegramUI/Components/AnimationCache/BUILD b/submodules/TelegramUI/Components/AnimationCache/BUILD index 3e79cc1f13..e655aa9fe6 100644 --- a/submodules/TelegramUI/Components/AnimationCache/BUILD +++ b/submodules/TelegramUI/Components/AnimationCache/BUILD @@ -13,7 +13,7 @@ swift_library( "//submodules/SSignalKit/SwiftSignalKit:SwiftSignalKit", "//submodules/CryptoUtils:CryptoUtils", "//submodules/ManagedFile:ManagedFile", - "//submodules/TelegramUI/Components/AnimationCache/DCT:DCT", + "//submodules/TelegramUI/Components/AnimationCache/ImageDCT:ImageDCT", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h b/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h deleted file mode 100644 index 01fa6dc26c..0000000000 --- a/submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/DCT.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef DctImageTransform_h -#define DctImageTransform_h - -#import - -#import - -NSData *generateForwardDctData(int quality); -void performForwardDct(uint8_t const *pixels, int16_t *coefficients, int width, int height, int bytesPerRow, NSData *dctData); - -NSData *generateInverseDctData(int quality); -void performInverseDct(int16_t const *coefficients, uint8_t *pixels, int width, int height, int coefficientsPerRow, int bytesPerRow, NSData *idctData); - -#endif /* DctImageTransform_h */ diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m b/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m deleted file mode 100644 index b01c769007..0000000000 --- a/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/DCT.m +++ /dev/null @@ -1,991 +0,0 @@ -#import - -typedef long JLONG; - -typedef unsigned char JSAMPLE; -#define GETJSAMPLE(value) ((int)(value)) - -#define MAXJSAMPLE 255 -#define CENTERJSAMPLE 128 - -typedef short JCOEF; - -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 JSAMPLE *JSAMPROW; /* ptr to one image row of pixel samples. */ -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 */ - -typedef JCOEF *JCOEFPTR; /* useful in a couple of places */ - -#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 -}; - -typedef short DCTELEM; /* prefer 16 bit with SIMD for parellelism */ -typedef unsigned short UDCTELEM; -typedef unsigned int UDCTELEM2; - -static void jsimd_fdct_ifast_neon(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); -} - -static void jsimd_idct_ifast_neon(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); -} - -static 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; -} - -static 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 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; -} - -static void jpeg_add_quant_table(DCTELEM *qtable, DCTELEM *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; - } -} - -static void jpeg_set_quality(DCTELEM *qtable, 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, std_luminance_quant_tbl, quality, false); -} - -static void getDivisors(DCTELEM *dtbl, DCTELEM *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])) { - //fdct->quantize = quantize; - printf("here\n"); - } - } -} - -static 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; - } -} - -NSData *generateForwardDctData(int quality) { - NSMutableData *divisors = [[NSMutableData alloc] initWithLength:DCTSIZE2 * 4 * sizeof(DCTELEM)]; - - DCTELEM qtable[DCTSIZE2]; - jpeg_set_quality(qtable, quality); - - getDivisors((DCTELEM *)divisors.mutableBytes, qtable); - - return divisors; -} - -NSData *generateInverseDctData(int quality) { - NSMutableData *divisors = [[NSMutableData alloc] initWithLength:DCTSIZE2 * sizeof(IFAST_MULT_TYPE)]; - IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)divisors.mutableBytes; - - DCTELEM qtable[DCTSIZE2]; - jpeg_set_quality(qtable, quality); - -#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); - } - - return divisors; -} - -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, NSData *dctData) { - DCTELEM *divisors = (DCTELEM *)dctData.bytes; - - 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; - } - } - - jsimd_fdct_ifast_neon(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, NSData *idctData) { - IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)idctData.bytes; - - 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)]; - } - } - - jsimd_idct_ifast_neon(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]; - } - } - } - } -} diff --git a/submodules/TelegramUI/Components/AnimationCache/DCT/BUILD b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/BUILD similarity index 72% rename from submodules/TelegramUI/Components/AnimationCache/DCT/BUILD rename to submodules/TelegramUI/Components/AnimationCache/ImageDCT/BUILD index f98db65bc2..030187e3e1 100644 --- a/submodules/TelegramUI/Components/AnimationCache/DCT/BUILD +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/BUILD @@ -1,10 +1,13 @@ objc_library( - name = "DCT", + name = "ImageDCT", enable_modules = True, - module_name = "DCT", + module_name = "ImageDCT", srcs = glob([ "Sources/**/*.m", + "Sources/**/*.mm", + "Sources/**/*.c", + "Sources/**/*.cpp", "Sources/**/*.h", ]), hdrs = glob([ 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..4f9a855d4f --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h @@ -0,0 +1,17 @@ +#ifndef DctImageTransform_h +#define DctImageTransform_h + +#import + +#import + +@interface ImageDCT : NSObject + +- (instancetype _Nonnull)initWithQuality:(NSInteger)quality; + +- (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/DCT/PublicHeaders/DCT/YuvConversion.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h similarity index 100% rename from submodules/TelegramUI/Components/AnimationCache/DCT/PublicHeaders/DCT/YuvConversion.h rename to submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/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..49e464e764 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp @@ -0,0 +1,376 @@ +#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 +}; + +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 *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, 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, std_luminance_quant_tbl, quality, false); +} + +void getDivisors(DCTELEM *dtbl, DCTELEM *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(int quality, std::vector &data) { + data.resize(DCTSIZE2 * 4 * sizeof(DCTELEM)); + + DCTELEM qtable[DCTSIZE2]; + jpeg_set_quality(qtable, quality); + + getDivisors((DCTELEM *)data.data(), qtable); +} + +void generateInverseDctData(int quality, std::vector &data) { + data.resize(DCTSIZE2 * sizeof(IFAST_MULT_TYPE)); + IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)data.data(); + + DCTELEM qtable[DCTSIZE2]; + jpeg_set_quality(qtable, quality); + +#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 { + +class DCTInternal { +public: + DCTInternal(int quality) { + auxiliaryData = createDctAuxiliaryData(); + + generateForwardDctData(quality, forwardDctData); + generateInverseDctData(quality, inverseDctData); + } + + ~DCTInternal() { + freeDctAuxiliaryData(auxiliaryData); + } + +public: + struct DctAuxiliaryData *auxiliaryData = nullptr; + std::vector forwardDctData; + std::vector inverseDctData; +}; + +DCT::DCT(int quality) { + _internal = new DCTInternal(quality); +} + +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..3b0ca4e772 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h @@ -0,0 +1,26 @@ +#ifndef DCT_H +#define DCT_H + +#include "DCTCommon.h" + +#include + +namespace dct { + +class DCTInternal; + +class DCT { +public: + DCT(int quality); + ~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..3d39105531 --- /dev/null +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm @@ -0,0 +1,31 @@ +#import + +#import + +#include "DCT.h" + +@interface ImageDCT () { + std::unique_ptr _dct; +} + +@end + +@implementation ImageDCT + +- (instancetype _Nonnull)initWithQuality:(NSInteger)quality { + self = [super init]; + if (self != nil) { + _dct = std::unique_ptr(new dct::DCT((int)quality)); + } + 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/DCT/Sources/YuvConversion.m b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m similarity index 98% rename from submodules/TelegramUI/Components/AnimationCache/DCT/Sources/YuvConversion.m rename to submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m index 25b244d5e1..41bd589754 100644 --- a/submodules/TelegramUI/Components/AnimationCache/DCT/Sources/YuvConversion.m +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m @@ -1,4 +1,4 @@ -#import +#import #import #import diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift index a30d8fd48f..120dc7ae8f 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -1,6 +1,6 @@ import Foundation import UIKit -import DCT +import ImageDCT final class ImagePlane { let width: Int @@ -134,13 +134,11 @@ extension ImageYUVA420 { final class DctData { let quality: Int - let dctData: Data - let idctData: Data + let dct: ImageDCT init(quality: Int) { self.quality = quality - self.dctData = generateForwardDctData(Int32(quality))! - self.idctData = generateInverseDctData(Int32(quality))! + self.dct = ImageDCT(quality: quality) } } @@ -174,7 +172,7 @@ extension ImageYUVA420 { targetPlane.data.withUnsafeMutableBytes { bytes in let coefficients = bytes.baseAddress!.assumingMemoryBound(to: UInt16.self) - performForwardDct(sourcePixels, coefficients, Int32(sourcePlane.width), Int32(sourcePlane.height), Int32(sourcePlane.bytesPerRow), dctData.dctData) + dctData.dct.forward(withPixels: sourcePixels, coefficients: coefficients, width: sourcePlane.width, height: sourcePlane.height, bytesPerRow: sourcePlane.bytesPerRow) } } } @@ -217,7 +215,7 @@ extension DctCoefficientsYUVA420 { targetPlane.data.withUnsafeMutableBytes { bytes in let pixels = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self) - performInverseDct(coefficients, pixels, Int32(sourcePlane.width), Int32(sourcePlane.height), Int32(targetPlane.bytesPerRow), Int32(sourcePlane.width), dctData.idctData) + dctData.dct.inverse(withCoefficients: coefficients, pixels: pixels, width: sourcePlane.width, height: sourcePlane.height, coefficientsPerRow: targetPlane.width, bytesPerRow: targetPlane.width) } } } diff --git a/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD b/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD new file mode 100644 index 0000000000..7813794065 --- /dev/null +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD @@ -0,0 +1,20 @@ +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", + ], + 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..6b2a4df214 --- /dev/null +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift @@ -0,0 +1,113 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit + +private final class ExpansionPanRecognizer: UIPanGestureRecognizer, UIGestureRecognizerDelegate { + private var targetScrollView: UIScrollView? + + override init(target: Any?, action: Selector?) { + super.init(target: target, action: action) + + self.delegate = self + } + + override func reset() { + self.targetScrollView = nil + } + + func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + /*if let scrollView = otherGestureRecognizer.view as? UIScrollView { + if scrollView.bounds.height > 200.0 { + self.targetScrollView = scrollView + scrollView.contentOffset = CGPoint() + } + }*/ + + return false + } + + override func touchesMoved(_ touches: Set, with event: UIEvent) { + super.touchesMoved(touches, with: event) + + if let targetScrollView = self.targetScrollView { + targetScrollView.contentOffset = 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 + + 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(in: self.view).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(in: self.view) + 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.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 collapse() { + self.expansionFraction = 0.0 + } +} diff --git a/submodules/TelegramUI/Components/EntityKeyboard/BUILD b/submodules/TelegramUI/Components/EntityKeyboard/BUILD index 5947ec2a2e..2c3681c3ec 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/BUILD +++ b/submodules/TelegramUI/Components/EntityKeyboard/BUILD @@ -33,6 +33,11 @@ swift_library( "//submodules/ShimmerEffect:ShimmerEffect", "//submodules/PhotoResources:PhotoResources", "//submodules/StickerResources:StickerResources", + "//submodules/AppBundle:AppBundle", + "//submodules/ContextUI:ContextUI", + "//submodules/PremiumUI:PremiumUI", + "//submodules/StickerPackPreviewUI:StickerPackPreviewUI", + "//submodules/UndoUI:UndoUI", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 5c03454d8a..132efd729c 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -17,6 +17,38 @@ import SwiftSignalKit import ShimmerEffect import PagerComponent import StickerResources +import AppBundle +import ContextUI +import PremiumUI +import StickerPackPreviewUI +import UndoUI + +private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) + +private final class PremiumBadgeView: BlurredBackgroundView { + private let iconLayer: SimpleLayer + + init() { + self.iconLayer = SimpleLayer() + self.iconLayer.contents = premiumBadgeIcon?.cgImage + + super.init(color: .clear, enableBlur: true) + + self.layer.addSublayer(self.iconLayer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(backgroundColor: UIColor, size: CGSize) { + self.updateColor(color: backgroundColor, transition: .immediate) + + self.iconLayer.frame = CGRect(origin: CGPoint(), size: size).insetBy(dx: 2.0, dy: 2.0) + + super.update(size: size, cornerRadius: min(size.width / 2.0, size.height / 2.0), transition: .immediate) + } +} public final class EmojiPagerContentComponent: Component { public typealias EnvironmentType = (EntityKeyboardChildEnvironment, PagerComponentChildEnvironment) @@ -25,25 +57,45 @@ public final class EmojiPagerContentComponent: Component { public let performItemAction: (Item, UIView, CGRect, CALayer) -> Void public let deleteBackwards: () -> Void public let openStickerSettings: () -> 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 (Item, UIView, CGRect, CALayer) -> Void, deleteBackwards: @escaping () -> Void, - openStickerSettings: @escaping () -> Void + openStickerSettings: @escaping () -> 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.pushController = pushController + self.presentController = presentController + self.presentGlobalOverlayController = presentGlobalOverlayController + self.navigationController = navigationController + self.sendSticker = sendSticker + self.chatPeerId = chatPeerId } } public final class Item: Equatable { public let emoji: String public let file: TelegramMediaFile + public let stickerPackItem: StickerPackItem? - public init(emoji: String, file: TelegramMediaFile) { + public init(emoji: String, file: TelegramMediaFile, stickerPackItem: StickerPackItem?) { self.emoji = emoji self.file = file + self.stickerPackItem = stickerPackItem } public static func ==(lhs: Item, rhs: Item) -> Bool { @@ -56,6 +108,9 @@ public final class EmojiPagerContentComponent: Component { if lhs.file.fileId != rhs.file.fileId { return false } + if lhs.stickerPackItem?.file.fileId != rhs.stickerPackItem?.file.fileId { + return false + } return true } @@ -268,6 +323,7 @@ public final class EmojiPagerContentComponent: Component { private let size: CGSize private var disposable: Disposable? private var fetchDisposable: Disposable? + private var premiumBadgeView: PremiumBadgeView? private var isInHierarchyValue: Bool = false public var isVisibleForAnimations: Bool = false { @@ -288,6 +344,8 @@ public final class EmojiPagerContentComponent: Component { cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, + blurredBadgeColor: UIColor, + displayPremiumBadgeIfAvailable: Bool, pointSize: CGSize ) { self.item = item @@ -365,6 +423,17 @@ public final class EmojiPagerContentComponent: Component { } } }) + + self.fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: isSmall)).start() + } + + if displayPremiumBadgeIfAvailable && file.isPremiumSticker { + let premiumBadgeView = PremiumBadgeView() + let badgeSize = CGSize(width: 20.0, height: 20.0) + premiumBadgeView.frame = CGRect(origin: CGPoint(x: pointSize.width - badgeSize.width, y: pointSize.height - badgeSize.height), size: badgeSize) + premiumBadgeView.update(backgroundColor: blurredBadgeColor, size: badgeSize) + self.premiumBadgeView = premiumBadgeView + self.addSublayer(premiumBadgeView.layer) } } @@ -434,6 +503,10 @@ public final class EmojiPagerContentComponent: Component { private var theme: PresentationTheme? private var itemLayout: ItemLayout? + private var currentContextGestureItemKey: ItemLayer.Key? + + private weak var peekController: PeekController? + override init(frame: CGRect) { self.scrollView = UIScrollView() @@ -452,6 +525,178 @@ public final class EmojiPagerContentComponent: Component { self.addSubview(self.scrollView) self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + + /*self.useSublayerTransformForActivation = false + self.shouldBegin = { [weak self] point in + guard let strongSelf = self else { + return false + } + if let item = strongSelf.item(atPoint: point), let itemLayer = strongSelf.visibleItemLayers[item.1] { + strongSelf.currentContextGestureItemKey = item.1 + strongSelf.targetLayerForActivationProgress = itemLayer + return true + } else { + return false + } + } + self.contextGesture?.cancelGesturesOnActivation = { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.scrollView.panGestureRecognizer.state = .failed + }*/ + + 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] else { + return nil + } + + let context = component.context + let accountPeerId = context.account.peerId + return combineLatest( + context.engine.stickers.isStickerSaved(id: item.0.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 sendSticker = component.inputInteraction.sendSticker, let chatPeerId = component.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: item.0.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil) + } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { + sendSticker(.standalone(media: item.0.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: item.0.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) + } else if let imageNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.imageNode { + let _ = sendSticker(.standalone(media: item.0.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: item.0.file, saved: !isStarred) + |> deliverOnMainQueue).start(next: { result in + switch result { + case .generic: + component.inputInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: item.0.file, title: nil, text: !isStarred ? presentationData.strings.Conversation_StickerAddedToFavorites : presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: 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.inputInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: item.0.file, title: presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { action in + if case .info = action { + let controller = PremiumIntroScreen(context: context, source: .savedStickers) + component.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 item.0.file.attributes { + switch attribute { + case let .Sticker(_, packReference, _): + if let packReference = packReference { + let controller = StickerPackScreen(context: context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: component.inputInteraction.navigationController(), sendSticker: { file, sourceView, sourceRect in + //return component.inputInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil) + return false + }) + + component.inputInteraction.navigationController()?.view.window?.endEditing(true) + component.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(item.0.file), isLocked: item.0.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + let controller = PremiumIntroScreen(context: context, source: .stickers) + component.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.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.addGestureRecognizer(peekRecognizer) } required init?(coder: NSCoder) { @@ -600,12 +845,26 @@ public final class EmojiPagerContentComponent: Component { if let current = self.visibleItemLayers[itemId] { itemLayer = current } else { - itemLayer = ItemLayer(item: item, context: component.context, groupId: "keyboard", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, cache: component.animationCache, renderer: component.animationRenderer, placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), pointSize: CGSize(width: itemLayout.itemSize, height: itemLayout.itemSize)) + itemLayer = ItemLayer( + item: item, + context: component.context, + groupId: "keyboard", + attemptSynchronousLoad: attemptSynchronousLoads, + file: item.file, + cache: component.animationCache, + renderer: component.animationRenderer, + placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), + blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), + displayPremiumBadgeIfAvailable: true, + pointSize: CGSize(width: itemLayout.itemSize, height: itemLayout.itemSize) + ) self.scrollView.layer.addSublayer(itemLayer) self.visibleItemLayers[itemId] = itemLayer } - itemLayer.frame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: index) + let itemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: index) + itemLayer.position = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + itemLayer.bounds = CGRect(origin: CGPoint(), size: itemFrame.size) itemLayer.isVisibleForAnimations = true } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 3bc7213fdd..5fbe61559c 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -31,6 +31,7 @@ public final class EntityKeyboardComponent: Component { public let emojiContent: EmojiPagerContentComponent public let stickerContent: EmojiPagerContentComponent public let gifContent: GifPagerContentComponent + public let defaultToEmojiTab: Bool public let externalTopPanelContainer: UIView? public let topPanelExtensionUpdated: (CGFloat, Transition) -> Void @@ -40,6 +41,7 @@ public final class EntityKeyboardComponent: Component { emojiContent: EmojiPagerContentComponent, stickerContent: EmojiPagerContentComponent, gifContent: GifPagerContentComponent, + defaultToEmojiTab: Bool, externalTopPanelContainer: UIView?, topPanelExtensionUpdated: @escaping (CGFloat, Transition) -> Void ) { @@ -48,6 +50,7 @@ public final class EntityKeyboardComponent: Component { self.emojiContent = emojiContent self.stickerContent = stickerContent self.gifContent = gifContent + self.defaultToEmojiTab = defaultToEmojiTab self.externalTopPanelContainer = externalTopPanelContainer self.topPanelExtensionUpdated = topPanelExtensionUpdated } @@ -68,6 +71,9 @@ public final class EntityKeyboardComponent: Component { if lhs.gifContent != rhs.gifContent { return false } + if lhs.defaultToEmojiTab != rhs.defaultToEmojiTab { + return false + } if lhs.externalTopPanelContainer != rhs.externalTopPanelContainer { return false } @@ -232,7 +238,7 @@ public final class EntityKeyboardComponent: Component { contentTopPanels: contentTopPanels, contentIcons: contentIcons, contentAccessoryRightButtons: contentAccessoryRightButtons, - defaultId: "emoji", + defaultId: component.defaultToEmojiTab ? "emoji" : "stickers", contentBackground: AnyComponent(BlurredBackgroundComponent( color: component.theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75) )), diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 1a3630a28c..69ee408867 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -63,7 +63,8 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { let itemLayer = EmojiPagerContentComponent.View.ItemLayer( item: EmojiPagerContentComponent.Item( emoji: "", - file: component.file + file: component.file, + stickerPackItem: nil ), context: component.context, groupId: "topPanel", @@ -72,6 +73,8 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { cache: component.animationCache, renderer: component.animationRenderer, placeholderColor: .lightGray, + blurredBadgeColor: .clear, + displayPremiumBadgeIfAvailable: false, pointSize: CGSize(width: 28.0, height: 28.0) ) self.itemLayer = itemLayer diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 5ee132edaf..f498039eb7 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1523,6 +1523,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { + strongSelf.chatDisplayNode.inputPanelContainerNode.collapse() strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { current in var current = current current = current.updatedInterfaceState { interfaceState in @@ -5313,7 +5314,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) @@ -9926,6 +9927,13 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G self.updateSlowmodeStatus() + switch updatedChatPresentationInterfaceState.inputMode { + case .media: + break + default: + self.chatDisplayNode.inputPanelContainerNode.collapse() + } + if self.isNodeLoaded { self.chatDisplayNode.updateChatPresentationInterfaceState(updatedChatPresentationInterfaceState, transition: transition, interactive: interactive, completion: completion) } else { @@ -9976,20 +9984,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) } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 82f9694478..3f67c5b134 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -18,6 +18,7 @@ import WallpaperBackgroundNode import GridMessageSelectionNode import SparseItemGrid import ChatPresentationInterfaceState +import ChatInputPanelContainer final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem { let itemNode: OverlayMediaItemNode @@ -68,6 +69,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,6 +83,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } + let contentContainerNode: ASDisplayNode + let contentDimNode: ASDisplayNode let backgroundNode: WallpaperBackgroundNode let historyNode: ChatHistoryListNode var blurredHistoryNode: ASImageNode? @@ -97,7 +101,10 @@ 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 @@ -240,17 +247,24 @@ 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 @@ -369,7 +383,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 @@ -501,25 +517,36 @@ 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.inputPanelContainerNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode) - - 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 + } + + strongSelf.requestLayout(transition) + } + + self.addSubnode(self.inputPanelContainerNode) + + self.inputPanelContainerNode.addSubnode(self.inputPanelClippingNode) + self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundNode) + self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundSeparatorNode) + self.inputPanelClippingNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode) + + self.contentContainerNode.addSubnode(self.inputContextPanelContainer) + 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) @@ -707,6 +734,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 { @@ -715,6 +758,62 @@ 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.updateDismissal(transition: transition, progress: animateFromFraction, additionalProgress: 0.0, completion: {}) + } + 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() + }) + } + transition.updateCornerRadius(node: self.inputPanelClippingNode, cornerRadius: 0.0, completion: { [weak self] completed in + guard let strongSelf = self, completed else { + return + } + strongSelf.inputPanelClippingNode.clipsToBounds = false + }) + } + + 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 { @@ -783,10 +882,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 } @@ -886,7 +985,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) @@ -903,85 +1002,21 @@ 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 + } - 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, makeMediaInputNode: { + 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() - }) { - 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 { - self.inputMediaNode = inputMediaNode - inputMediaNode.requestDisableStickerAnimations = { [weak self] disabled in - self?.controller?.disableStickerAnimations = disabled - } - } - if self.inputNode != inputNode { - inputNode.topBackgroundExtensionUpdated = { [weak self] transition in - self?.updateInputPanelBackgroundExtension(transition: transition) - } - - 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 self.inputMediaNode != nil { - if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { - self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: inputPanelNode) - } else { - self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) - } - } else { - self.inputPanelContainerNode.insertSubnode(inputNode, belowSubnode: self.inputPanelBackgroundNode) - } - - if let externalTopPanelContainer = inputNode.externalTopPanelContainer { - if let inputPanelNode = self.inputPanelNode, inputPanelNode.supernode != nil { - self.inputPanelContainerNode.view.insertSubview(externalTopPanelContainer, belowSubview: inputPanelNode.view) - } else { - self.inputPanelContainerNode.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) - } else if let inputNode = self.inputNode { - dismissedInputNode = inputNode - dismissedInputNodeInputBackgroundExtension = inputNode.topBackgroundExtension - dismissedInputNodeExternalTopPanelContainer = inputNode.externalTopPanelContainer - self.inputNode = nil - } - - var effectiveInputNodeHeight: CGFloat? - if let inputNodeHeightAndOverflow = inputNodeHeightAndOverflow { - if let upperInputPositionBound = self.upperInputPositionBound { - effectiveInputNodeHeight = max(0.0, min(layout.size.height - max(0.0, upperInputPositionBound), inputNodeHeightAndOverflow.0)) - } else { - effectiveInputNodeHeight = inputNodeHeightAndOverflow.0 - } - } + }) var insets: UIEdgeInsets - var bottomOverflowOffset: CGFloat = 0.0 - if let effectiveInputNodeHeight = effectiveInputNodeHeight, let inputNodeHeightAndOverflow = inputNodeHeightAndOverflow { + if inputNodeForState != nil { insets = layout.insets(options: []) - insets.bottom = max(effectiveInputNodeHeight, insets.bottom) - bottomOverflowOffset = inputNodeHeightAndOverflow.1 + insets.bottom = max(insets.bottom, layout.standardInputHeight) } else { insets = layout.insets(options: [.input]) } @@ -992,17 +1027,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { insets.top += navigationBarHeight } - var wrappingInsets = UIEdgeInsets() - if case .overlay = self.chatPresentationInterfaceState.mode { - let containerWidth = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: 8.0 + layout.safeInsets.left) - wrappingInsets.left = floor((layout.size.width - containerWidth) / 2.0) - wrappingInsets.right = wrappingInsets.left - - wrappingInsets.top = 8.0 - if let statusBarHeight = layout.statusBarHeight, CGFloat(40.0).isLess(than: statusBarHeight) { - wrappingInsets.top += statusBarHeight - } - } + var inputPanelSize: CGSize? + var immediatelyLayoutInputPanelAndAnimateAppearance = false + var secondaryInputPanelSize: CGSize? + var immediatelyLayoutSecondaryInputPanelAndAnimateAppearance = false + var inputPanelNodeHandlesTransition = false var dismissedInputPanelNode: ASDisplayNode? var dismissedSecondaryInputPanelNode: ASDisplayNode? @@ -1010,27 +1039,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 - } else if case .pinnedMessages = self.chatPresentationInterfaceState.subject { - 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 { @@ -1054,7 +1062,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputPanelNode = inputPanelNode if inputPanelNode.supernode !== self { immediatelyLayoutInputPanelAndAnimateAppearance = true - self.inputPanelContainerNode.insertSubnode(inputPanelNode, aboveSubnode: self.inputPanelBackgroundNode) + 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 - insets.bottom - 120.0, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) @@ -1073,7 +1081,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.secondaryInputPanelNode = secondaryInputPanelNode if secondaryInputPanelNode.supernode == nil { immediatelyLayoutSecondaryInputPanelAndAnimateAppearance = true - self.inputPanelContainerNode.insertSubnode(secondaryInputPanelNode, aboveSubnode: self.inputPanelBackgroundNode) + 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 - insets.bottom, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) @@ -1083,6 +1091,164 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { dismissedSecondaryInputPanelNode = self.secondaryInputPanelNode self.secondaryInputPanelNode = nil } + + 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.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 { + 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 = 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 { + self.inputMediaNode = inputMediaNode + inputMediaNode.requestDisableStickerAnimations = { [weak self] disabled in + self?.controller?.disableStickerAnimations = disabled + } + } + if self.inputNode != inputNode { + inputNode.topBackgroundExtensionUpdated = { [weak self] transition in + self?.updateInputPanelBackgroundExtension(transition: transition) + } + inputNode.expansionFractionUpdated = { [weak self] transition in + self?.updateInputPanelBackgroundExpansion(transition: transition) + } + + 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 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.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) + } + } + } + + 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) + + let boundedHeight = min(heightAndOverflow.0, layout.standardInputHeight) + + inputNodeHeightAndOverflow = ( + boundedHeight, + max(0.0, inputHeight - boundedHeight) + ) + } else if let inputNode = self.inputNode { + dismissedInputNode = inputNode + dismissedInputNodeInputBackgroundExtension = inputNode.topBackgroundExtension + dismissedInputNodeExternalTopPanelContainer = inputNode.externalTopPanelContainer + self.inputNode = nil + } + + var effectiveInputNodeHeight: CGFloat? + if let inputNodeHeightAndOverflow = inputNodeHeightAndOverflow { + if let upperInputPositionBound = self.upperInputPositionBound { + effectiveInputNodeHeight = max(0.0, min(layout.size.height - max(0.0, upperInputPositionBound), inputNodeHeightAndOverflow.0)) + } else { + effectiveInputNodeHeight = inputNodeHeightAndOverflow.0 + } + } + + var bottomOverflowOffset: CGFloat = 0.0 + if let effectiveInputNodeHeight = effectiveInputNodeHeight, let inputNodeHeightAndOverflow = inputNodeHeightAndOverflow { + insets.bottom = max(effectiveInputNodeHeight, insets.bottom) + bottomOverflowOffset = inputNodeHeightAndOverflow.1 + } + + var wrappingInsets = UIEdgeInsets() + if case .overlay = self.chatPresentationInterfaceState.mode { + let containerWidth = horizontalContainerFillingSizeForLayout(layout: layout, sideInset: 8.0 + layout.safeInsets.left) + wrappingInsets.left = floor((layout.size.width - containerWidth) / 2.0) + wrappingInsets.right = wrappingInsets.left + + wrappingInsets.top = 8.0 + if let statusBarHeight = layout.statusBarHeight, CGFloat(40.0).isLess(than: statusBarHeight) { + wrappingInsets.top += statusBarHeight + } + } + + var isSelectionEnabled = true + if previewing { + isSelectionEnabled = false + } else if case .pinnedMessages = self.chatPresentationInterfaceState.subject { + isSelectionEnabled = false + } + self.historyNode.isSelectionGestureEnabled = isSelectionEnabled 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) @@ -1106,7 +1272,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)) @@ -1133,45 +1299,6 @@ 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 inputContextPanelNode !== self.inputContextPanelNode { @@ -1192,7 +1319,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { dismissedOverlayContextPanelNode = self.overlayContextPanelNode self.overlayContextPanelNode = overlayContextPanelNode - self.addSubnode(overlayContextPanelNode) + self.contentContainerNode.addSubnode(overlayContextPanelNode) immediatelyLayoutOverlayContextPanelAndAnimateAppearance = true } } else if let overlayContextPanelNode = self.overlayContextPanelNode { @@ -1345,7 +1472,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)) @@ -1382,7 +1509,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) } @@ -1403,10 +1530,20 @@ 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)) + 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) + transition.updateBounds(node: self.inputPanelClippingNode, bounds: CGRect(origin: CGPoint(x: 0.0, y: apparentInputBackgroundFrame.origin.y), size: layout.size)) transition.updateFrame(node: self.inputPanelBackgroundNode, frame: apparentInputBackgroundFrame) + 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 @@ -1795,6 +1932,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { transition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBackgroundNode.frame.maxY + extensionValue), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) } + private func updateInputPanelBackgroundExpansion(transition: ContainedViewLayoutTransition) { + self.requestLayout(transition) + } + private func notifyTransitionCompletionListeners(transition: ContainedViewLayoutTransition) { if !self.onLayoutCompletions.isEmpty { let onLayoutCompletions = self.onLayoutCompletions @@ -2107,7 +2248,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } let _ = peerId - let inputNode = ChatEntityKeyboardInputNode(context: self.context, currentInputData: inputMediaNodeData, updatedInputData: self.inputMediaNodeDataPromise.get()) + let inputNode = ChatEntityKeyboardInputNode(context: self.context, currentInputData: inputMediaNodeData, updatedInputData: self.inputMediaNodeDataPromise.get(), defaultToEmojiTab: !self.chatPresentationInterfaceState.interfaceState.effectiveInputState.inputText.string.isEmpty) return inputNode } @@ -2116,10 +2257,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if !self.didInitializeInputMediaNodeDataPromise, let interfaceInteraction = self.interfaceInteraction { self.didInitializeInputMediaNodeDataPromise = true - self.inputMediaNodeDataPromise.set(ChatEntityKeyboardInputNode.inputData(context: self.context, interfaceInteraction: interfaceInteraction, controllerInteraction: self.controllerInteraction)) + self.inputMediaNodeDataPromise.set(ChatEntityKeyboardInputNode.inputData(context: self.context, interfaceInteraction: interfaceInteraction, controllerInteraction: self.controllerInteraction, chatPeerId: self.chatLocation.peerId)) } - if self.inputMediaNode == nil && !self.context.sharedContext.immediateExperimentalUISettings.inlineStickers { + 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 { @@ -2420,7 +2561,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) @@ -2713,7 +2854,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 { @@ -2722,6 +2863,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/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 0fbdb124a7..d3e258ebe2 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -32,7 +32,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction, controllerInteraction: ChatControllerInteraction) -> Signal { + 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 @@ -67,7 +67,35 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { interfaceInteraction.backwardsDeleteText() }, openStickerSettings: { - } + }, + 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 ) let stickerInputInteraction = EmojiPagerContentComponent.InputInteraction( performItemAction: { [weak interfaceInteraction] item, view, rect, layer in @@ -89,7 +117,35 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let controller = installedStickerPacksController(context: context, mode: .modal) controller.navigationPresentation = .modal controllerInteraction.navigationController()?.pushViewController(controller) - } + }, + 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 ) let gifInputInteraction = GifPagerContentComponent.InputInteraction( performItemAction: { [weak controllerInteraction] item, view, rect in @@ -134,7 +190,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { if emojiCollectionIds.contains(entry.index.collectionId) { let resultItem = EmojiPagerContentComponent.Item( emoji: "", - file: item.file + file: item.file, + stickerPackItem: nil ) let groupId = entry.index.collectionId @@ -221,7 +278,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let resultItem = EmojiPagerContentComponent.Item( emoji: "", - file: item.file + file: item.file, + stickerPackItem: nil ) let groupId = "saved" @@ -246,7 +304,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let resultItem = EmojiPagerContentComponent.Item( emoji: "", - file: item.media + file: item.media, + stickerPackItem: nil ) let groupId = "recent" @@ -294,7 +353,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let resultItem = EmojiPagerContentComponent.Item( emoji: "", - file: item.media + file: item.media, + stickerPackItem: nil ) let groupId = "premium" @@ -313,7 +373,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } let resultItem = EmojiPagerContentComponent.Item( emoji: "", - file: item.file + file: item.file, + stickerPackItem: item ) let groupId = entry.index.collectionId if let groupIndex = itemGroupIndexById[groupId] { @@ -385,11 +446,16 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private let entityKeyboardView: ComponentHostView + private let defaultToEmojiTab: Bool private var currentInputData: InputData private var inputDataDisposable: Disposable? - init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal) { + 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)? + + init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool) { self.currentInputData = currentInputData + self.defaultToEmojiTab = defaultToEmojiTab + self.entityKeyboardView = ComponentHostView() super.init() @@ -404,6 +470,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return } strongSelf.currentInputData = inputData + strongSelf.performLayout() }) } @@ -411,7 +478,18 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.inputDataDisposable?.dispose() } + private func performLayout() { + guard let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) = self.currentState else { + return + } + 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) + } + 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) { + self.currentState = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) + + let expandedHeight = standardInputHeight + self.expansionFraction * (maximumHeight - standardInputHeight) + let entityKeyboardSize = self.entityKeyboardView.update( transition: Transition(transition), component: AnyComponent(EntityKeyboardComponent( @@ -420,6 +498,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { emojiContent: self.currentInputData.emoji, stickerContent: self.currentInputData.stickers, gifContent: self.currentInputData.gifs, + defaultToEmojiTab: self.defaultToEmojiTab, externalTopPanelContainer: self.externalTopPanelContainer, topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in guard let strongSelf = self else { @@ -432,10 +511,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } )), environment: {}, - containerSize: CGSize(width: width, height: standardInputHeight) + containerSize: CGSize(width: width, height: expandedHeight) ) transition.updateFrame(view: self.entityKeyboardView, frame: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: entityKeyboardSize)) - return (standardInputHeight, 0.0) + return (expandedHeight, 0.0) } } diff --git a/submodules/TelegramUI/Sources/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index d365208a9f..da22776da3 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -16,6 +16,9 @@ class ChatInputNode: ASDisplayNode { var topBackgroundExtension: CGFloat = 41.0 var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> Void)? + var expansionFraction: CGFloat = 0.0 + var expansionFractionUpdated: ((ContainedViewLayoutTransition) -> 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) { return (0.0, 0.0) } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift index 031c020cfa..a988e0bdc1 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputNodes.swift @@ -12,7 +12,7 @@ func inputNodeForChatPresentationIntefaceState(_ chatPresentationInterfaceState: } switch chatPresentationInterfaceState.inputMode { case .media: - if context.sharedContext.immediateExperimentalUISettings.inlineStickers { + if "".isEmpty { if let currentNode = currentNode as? ChatEntityKeyboardInputNode { return currentNode } else if let inputMediaNode = inputMediaNode { diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index f6cdf73996..4870710465 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -958,7 +958,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 } @@ -1592,7 +1592,7 @@ 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 { @@ -1694,7 +1694,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,7 +1744,7 @@ 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 { @@ -1849,7 +1849,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 +1866,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) diff --git a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift index 8c9fb1451f..06bdc56632 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift @@ -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/ChatMessageTransitionNode.swift b/submodules/TelegramUI/Sources/ChatMessageTransitionNode.swift index bf079a44e7..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() @@ -430,7 +438,7 @@ public final class ChatMessageTransitionNode: ASDisplayNode { 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 = sourceContainerView.convert(sourceRect, to: self.view) + sourceAbsoluteRect = convertAnimatingSourceRect(sourceRect, fromView: sourceContainerView, toView: self.view) case let .inputPanelSearch(sourceItemNode): 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) diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 59a51c5c83..e7ba397f5e 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -1840,7 +1840,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) @@ -2294,7 +2300,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } if mediaInputIsActive { - hideMicButton = true + //hideMicButton = true } if hideMicButton { diff --git a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift index 2c5e72a1c4..cdae308f0c 100644 --- a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift +++ b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift @@ -478,7 +478,7 @@ 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 = [ @@ -550,7 +550,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,7 +570,7 @@ 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 = [ @@ -638,7 +638,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 +651,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) @@ -1180,7 +1180,7 @@ private final class FeaturedPaneSearchContentNode: ASDisplayNode { 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 +1426,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/HorizontalListContextResultsChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift index a705670b73..c66d66445e 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -144,7 +144,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 { @@ -175,7 +175,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 +228,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/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index 930cdacc64..8eeca26f7b 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -16,7 +16,7 @@ import PremiumUI import UndoUI final class HorizontalStickersChatContextPanelInteraction { - var previewedStickerItem: StickerPackItem? + var previewedStickerItem: TelegramMediaFile? } private func backgroundCenterImage(_ theme: PresentationTheme) -> UIImage? { @@ -173,7 +173,7 @@ 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 = [ @@ -241,7 +241,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 +255,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 +267,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 +366,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 9a0280d1eb..4cac521101 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -42,7 +42,7 @@ 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, UIView, CGRect) -> Void)? @@ -101,7 +101,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] = [] @@ -196,7 +196,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 +210,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 +226,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,7 +433,7 @@ 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 + return item.file.fileId == self?.previewedStickerItem?.fileId }, sendSticker: { [weak self] file, view, rect in self?.sendSticker?(file, view, rect) } diff --git a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift index 92ea1c0b39..b78c2e6063 100644 --- a/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/StickerPaneSearchContentNode.swift @@ -186,7 +186,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() @@ -324,7 +324,7 @@ final class StickerPaneSearchContentNode: ASDisplayNode, PaneSearchContentNode { 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 +561,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 +569,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/StickersChatInputContextPanelItem.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift index d313b5cb28..ea088a38f6 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelItem.swift @@ -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 f72a055c94..1de8bf6eda 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -20,7 +20,7 @@ private struct StickersChatInputContextPanelEntryStableId: Hashable { } final class StickersChatInputContextPanelInteraction { - var previewedStickerItem: StickerPackItem? + var previewedStickerItem: TelegramMediaFile? } private struct StickersChatInputContextPanelEntry: Identifiable, Comparable { @@ -129,7 +129,7 @@ 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 = [ @@ -197,7 +197,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 +212,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 +224,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 { From 4a9c3dacc8315fdbe7a4bd47e20a1e125db14ef5 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 30 Jun 2022 16:44:17 +0300 Subject: [PATCH 019/113] Update account deletion API --- .../Sources/ChannelVisibilityController.swift | 2 +- .../Sources/DeleteAccountDataController.swift | 12 +++--- submodules/TelegramApi/Sources/Api27.swift | 8 ++-- .../TelegramCore/Sources/Authorization.swift | 2 +- .../Auth/TelegramEngineAuth.swift | 39 ++++++++++++++++--- .../Sources/ApplicationContext.swift | 2 +- 6 files changed, 48 insertions(+), 17 deletions(-) diff --git a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift index 5313ec7bbe..c7cb1f99d1 100644 --- a/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift +++ b/submodules/PeerInfoUI/Sources/ChannelVisibilityController.swift @@ -1147,7 +1147,7 @@ public func channelVisibilityController(context: AccountContext, updatedPresenta let _ = combineLatest( queue: Queue.mainQueue(), adminedPublicChannels.get() |> filter { $0 != nil } |> take(1), - context.engine.data.subscribe(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)), + context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.account.peerId)), context.engine.data.get( TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: false), TelegramEngine.EngineData.Item.Configuration.UserLimits(isPremium: true) diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index 8396eb6eb5..04be040592 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -387,7 +387,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat proceedImpl = { [weak controller] in let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let action: ([EnginePeer]) -> Void = { preloadedPeers in + let action: ([EnginePeer], String?) -> Void = { preloadedPeers, password in let nextMode: DeleteAccountDataMode? switch mode { case .peers: @@ -423,7 +423,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let accountId = context.account.id let accountManager = context.sharedContext.accountManager - let _ = (context.engine.auth.deleteAccount(reason: "Manual") + let _ = (context.engine.auth.deleteAccount(reason: "Manual", password: password) |> deliverOnMainQueue).start(error: { _ in updateState { current in var updated = current @@ -447,7 +447,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let _ = (preloadedGroupPeers.get() |> take(1) |> deliverOnMainQueue).start(next: { peers in - action(peers) + action(peers, nil) }) case .phone: var phoneNumber: String? @@ -469,7 +469,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.DeleteAccount_InvalidPhoneNumberError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])) return } - action([]) + action([], nil) } }) } @@ -507,13 +507,13 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat return updated } - action([]) + action([], state.password) }) return } default: - action([]) + action([], nil) } } diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index a7cbb13c79..d5594303ec 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -156,11 +156,13 @@ public extension Api.functions.account { } } public extension Api.functions.account { - static func deleteAccount(reason: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func deleteAccount(flags: Int32, reason: String, password: Api.InputCheckPasswordSRP?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(1099779595) + buffer.appendInt32(-1564422284) + serializeInt32(flags, buffer: buffer, boxed: false) serializeString(reason, buffer: buffer, boxed: false) - return (FunctionDescription(name: "account.deleteAccount", parameters: [("reason", String(describing: reason))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + 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() { diff --git a/submodules/TelegramCore/Sources/Authorization.swift b/submodules/TelegramCore/Sources/Authorization.swift index 6624cbd1c0..3fdc5c5ea4 100644 --- a/submodules/TelegramCore/Sources/Authorization.swift +++ b/submodules/TelegramCore/Sources/Authorization.swift @@ -494,7 +494,7 @@ public enum AccountResetError { } public func performAccountReset(account: UnauthorizedAccount) -> Signal { - return account.network.request(Api.functions.account.deleteAccount(reason: "")) + return account.network.request(Api.functions.account.deleteAccount(flags: 0, reason: "", password: nil)) |> map { _ -> Int32? in return nil } |> `catch` { error -> Signal in if error.errorDescription.hasPrefix("2FA_CONFIRM_WAIT_") { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift index 09b6201252..b5b82e059f 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Auth/TelegramEngineAuth.swift @@ -90,12 +90,41 @@ public extension TelegramEngine { return _internal_updateTwoStepVerificationPassword(network: self.account.network, currentPassword: currentPassword, updatedPassword: updatedPassword) } - public func deleteAccount(reason: String) -> Signal { - return self.account.network.request(Api.functions.account.deleteAccount(reason: reason)) - |> mapError { _ -> DeleteAccountError in - return .generic + public func deleteAccount(reason: String, password: String?) -> Signal { + let network = self.account.network + + let passwordSignal: Signal + if let password = password { + passwordSignal = _internal_twoStepAuthData(network) + |> mapError { _ -> DeleteAccountError in + return .generic + } + |> mapToSignal { authData -> Signal in + if let currentPasswordDerivation = authData.currentPasswordDerivation, let srpSessionData = authData.srpSessionData { + guard let kdfResult = passwordKDF(encryptionProvider: network.encryptionProvider, password: password, derivation: currentPasswordDerivation, srpSessionData: srpSessionData) else { + return .fail(.generic) + } + return .single(.inputCheckPasswordSRP(srpId: kdfResult.id, A: Buffer(data: kdfResult.A), M1: Buffer(data: kdfResult.M1))) + } else { + return .single(nil) + } + } + } else { + passwordSignal = .single(nil) + } + + return passwordSignal + |> mapToSignal { password -> Signal in + var flags: Int32 = 0 + if let _ = password { + flags |= (1 << 0) + } + return self.account.network.request(Api.functions.account.deleteAccount(flags: flags, reason: reason, password: password)) + |> mapError { _ -> DeleteAccountError in + return .generic + } + |> ignoreValues } - |> ignoreValues } public func updateTwoStepVerificationEmail(currentPassword: String, updatedEmail: String) -> Signal { diff --git a/submodules/TelegramUI/Sources/ApplicationContext.swift b/submodules/TelegramUI/Sources/ApplicationContext.swift index edba458be9..adef8abf1a 100644 --- a/submodules/TelegramUI/Sources/ApplicationContext.swift +++ b/submodules/TelegramUI/Sources/ApplicationContext.swift @@ -486,7 +486,7 @@ final class AuthorizedApplicationContext { } let accountId = strongSelf.context.account.id let accountManager = strongSelf.context.sharedContext.accountManager - let _ = (strongSelf.context.engine.auth.deleteAccount(reason: "GDPR") + let _ = (strongSelf.context.engine.auth.deleteAccount(reason: "GDPR", password: nil) |> deliverOnMainQueue).start(error: { _ in guard let strongSelf = self else { return From f288fe8edac8abab778a2f1a119656a904a47b28 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 30 Jun 2022 16:44:44 +0300 Subject: [PATCH 020/113] Update API --- .../Sources/InAppPurchaseManager.swift | 4 +- submodules/TelegramApi/Sources/Api0.swift | 7 ++- submodules/TelegramApi/Sources/Api10.swift | 28 +++++++++++ submodules/TelegramApi/Sources/Api20.swift | 18 ++++--- submodules/TelegramApi/Sources/Api27.swift | 14 +++--- submodules/TelegramApi/Sources/Api9.swift | 50 +++++++++++++++++++ .../ApiUtils/StoreMessage_Telegram.swift | 2 +- .../ApiUtils/TelegramMediaAction.swift | 2 + .../SyncCore_TelegramMediaAction.swift | 8 +++ .../TelegramEngine/Payments/AppStore.swift | 48 ++++++++++++++---- .../Payments/TelegramEnginePayments.swift | 4 +- .../Peers/UpdateCachedPeerData.swift | 4 +- .../Sources/ServiceMessageStrings.swift | 2 + .../AnimationCache/Sources/ImageData.swift | 4 +- 14 files changed, 161 insertions(+), 34 deletions(-) diff --git a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift index 21f7dc3d6c..3ed74340d3 100644 --- a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift +++ b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift @@ -307,7 +307,7 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), sending receipt for transactions [\(transactionIds)]") self.disposableSet.set( - self.engine.payments.sendAppStoreReceipt(receipt: getReceiptData() ?? Data(), restore: false).start(error: { [weak self] _ in + self.engine.payments.sendAppStoreReceipt(receipt: getReceiptData() ?? Data(), purpose: .subscription).start(error: { [weak self] _ in Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), transactions [\(transactionIds)] failed to assign") for transaction in transactions { self?.stateQueue.async { @@ -337,7 +337,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/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 560e7fde82..0b6f984df3 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -347,6 +347,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { 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[1147243133] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentGiftPremium($0) } + dict[-764193027] = { 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 +413,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[380460460] = { 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) } @@ -828,7 +831,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[-1514584156] = { 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) } @@ -1322,6 +1325,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: diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index e99bde0f5d..cd54c48a54 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -1005,6 +1005,7 @@ public extension Api { case messageActionEmpty case messageActionGameScore(gameId: Int64, score: Int32) case messageActionGeoProximityReached(fromId: Api.Peer, toId: Api.Peer, distance: Int32) + case messageActionGiftPremium(currency: String, amount: Int64, duration: Int32) case messageActionGroupCall(flags: Int32, call: Api.InputGroupCall, duration: Int32?) case messageActionGroupCallScheduled(call: Api.InputGroupCall, scheduleDate: Int32) case messageActionHistoryClear @@ -1138,6 +1139,14 @@ public extension Api { toId.serialize(buffer, true) serializeInt32(distance, buffer: buffer, boxed: false) break + case .messageActionGiftPremium(let currency, let amount, let duration): + if boxed { + buffer.appendInt32(380460460) + } + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(amount, buffer: buffer, boxed: false) + serializeInt32(duration, buffer: buffer, boxed: false) + break case .messageActionGroupCall(let flags, let call, let duration): if boxed { buffer.appendInt32(2047704898) @@ -1297,6 +1306,8 @@ public extension Api { 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 duration): + return ("messageActionGiftPremium", [("currency", String(describing: currency)), ("amount", String(describing: amount)), ("duration", String(describing: duration))]) 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): @@ -1510,6 +1521,23 @@ public extension Api { return nil } } + public static func parse_messageActionGiftPremium(_ reader: BufferReader) -> MessageAction? { + var _1: String? + _1 = parseString(reader) + 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.MessageAction.messageActionGiftPremium(currency: _1!, amount: _2!, duration: _3!) + } + else { + return nil + } + } public static func parse_messageActionGroupCall(_ reader: BufferReader) -> MessageAction? { var _1: Int32? _1 = reader.readInt32() diff --git a/submodules/TelegramApi/Sources/Api20.swift b/submodules/TelegramApi/Sources/Api20.swift index 8a3362dbfb..c32090fe33 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -566,13 +566,13 @@ public extension Api { } 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?) + 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?, giftPremiumUrl: String?) 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): + 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 giftPremiumUrl): if boxed { - buffer.appendInt32(-1938625919) + buffer.appendInt32(-1514584156) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt64(id, buffer: buffer, boxed: false) @@ -589,14 +589,15 @@ public extension Api { 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 {serializeString(giftPremiumUrl!, buffer: buffer, boxed: false)} 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))]) + 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 giftPremiumUrl): + 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)), ("giftPremiumUrl", String(describing: giftPremiumUrl))]) } } @@ -643,6 +644,8 @@ public extension Api { if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() { _15 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights } } + var _16: String? + if Int(_1!) & Int(1 << 19) != 0 {_16 = parseString(reader) } let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil @@ -658,8 +661,9 @@ public extension Api { 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) + 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, giftPremiumUrl: _16) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index d5594303ec..8bf8658194 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -6229,12 +6229,13 @@ public extension Api.functions.messages { } } public extension Api.functions.payments { - static func assignAppStoreTransaction(flags: Int32, receipt: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func assignAppStoreTransaction(flags: Int32, receipt: Buffer, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(224186320) + buffer.appendInt32(296120783) 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 + purpose.serialize(buffer, true) + return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("flags", String(describing: flags)), ("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() { @@ -6245,11 +6246,12 @@ public extension Api.functions.payments { } } public extension Api.functions.payments { - static func assignPlayMarketTransaction(purchaseToken: String) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func assignPlayMarketTransaction(purchaseToken: String, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(1336560365) + buffer.appendInt32(-179907586) serializeString(purchaseToken, buffer: buffer, boxed: false) - return (FunctionDescription(name: "payments.assignPlayMarketTransaction", parameters: [("purchaseToken", String(describing: purchaseToken))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + purpose.serialize(buffer, true) + return (FunctionDescription(name: "payments.assignPlayMarketTransaction", parameters: [("purchaseToken", String(describing: purchaseToken)), ("purpose", String(describing: purpose))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { diff --git a/submodules/TelegramApi/Sources/Api9.swift b/submodules/TelegramApi/Sources/Api9.swift index fc80ab45ba..8b493b854d 100644 --- a/submodules/TelegramApi/Sources/Api9.swift +++ b/submodules/TelegramApi/Sources/Api9.swift @@ -454,6 +454,56 @@ public extension Api { } } +public extension Api { + enum InputStorePaymentPurpose: TypeConstructorDescription { + case inputStorePaymentGiftPremium(userId: Api.InputUser) + case inputStorePaymentPremiumSubscription + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputStorePaymentGiftPremium(let userId): + if boxed { + buffer.appendInt32(1147243133) + } + userId.serialize(buffer, true) + break + case .inputStorePaymentPremiumSubscription: + if boxed { + buffer.appendInt32(-764193027) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputStorePaymentGiftPremium(let userId): + return ("inputStorePaymentGiftPremium", [("userId", String(describing: userId))]) + case .inputStorePaymentPremiumSubscription: + return ("inputStorePaymentPremiumSubscription", []) + } + } + + 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 + } + let _c1 = _1 != nil + if _c1 { + return Api.InputStorePaymentPurpose.inputStorePaymentGiftPremium(userId: _1!) + } + else { + return nil + } + } + public static func parse_inputStorePaymentPremiumSubscription(_ reader: BufferReader) -> InputStorePaymentPurpose? { + return Api.InputStorePaymentPurpose.inputStorePaymentPremiumSubscription + } + + } +} public extension Api { enum InputTheme: TypeConstructorDescription { case inputTheme(id: Int64, accessHash: Int64) diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 536de15183..11668c41b7 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))) diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift index cd4492c8cb..3c4b065802 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, duration): + return TelegramMediaAction(action: .giftPremium(currency: currency, amount: amount, duration: duration)) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift index 48bf5de03f..b1a1d376b3 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, duration: 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), duration: decoder.decodeInt32ForKey("duration", 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, duration): + encoder.encodeInt32(27, forKey: "_rawValue") + encoder.encodeString(currency, forKey: "currency") + encoder.encodeInt64(amount, forKey: "amount") + encoder.encodeInt32(duration, forKey: "duration") } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index b7e51a0c15..5f3a8d57a3 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -10,22 +10,48 @@ public enum AssignAppStoreTransactionError { case serverProvided } -func _internal_sendAppStoreReceipt(account: Account, receipt: Data, restore: Bool) -> Signal { +public enum AppStoreTransactionPurpose { + case subscription + case gift(EnginePeer.Id) + case restore +} + +func _internal_sendAppStoreReceipt(account: Account, receipt: Data, purpose: AppStoreTransactionPurpose) -> Signal { var flags: Int32 = 0 - if restore { + if case .restore = purpose { 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 + + var purposeSignal: Signal + switch purpose { + case .subscription, .restore: + purposeSignal = .single(.inputStorePaymentPremiumSubscription) + case let .gift(peerId): + purposeSignal = account.postbox.loadedPeerWithId(peerId) + |> mapToSignal { peer -> Signal in + if let inputUser = apiInputUser(peer) { + return .single(.inputStorePaymentGiftPremium(userId: inputUser)) + } 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(flags: flags, 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() + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift index 8afeb78d59..7e2f1a8556 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/TelegramEnginePayments.swift @@ -38,8 +38,8 @@ 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 { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 9cafdf198b..511c198288 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,7 +234,7 @@ 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, _, _, _, _): let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:)) let isBlocked = (userFullFlags & (1 << 0)) != 0 let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0 diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 6297ea853e..19804dd893 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -652,6 +652,8 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, } case let .webViewData(text): attributedString = NSAttributedString(string: strings.Notification_WebAppSentData(text).string, font: titleFont, textColor: primaryTextColor) + case .giftPremium: + attributedString = nil case .unknown: attributedString = nil } diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift index a30d8fd48f..0254d1e53e 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -172,7 +172,7 @@ extension ImageYUVA420 { let sourcePixels = sourceBytes.baseAddress!.assumingMemoryBound(to: UInt8.self) targetPlane.data.withUnsafeMutableBytes { bytes in - let coefficients = bytes.baseAddress!.assumingMemoryBound(to: UInt16.self) + let coefficients = bytes.baseAddress!.assumingMemoryBound(to: Int16.self) performForwardDct(sourcePixels, coefficients, Int32(sourcePlane.width), Int32(sourcePlane.height), Int32(sourcePlane.bytesPerRow), dctData.dctData) } @@ -212,7 +212,7 @@ extension DctCoefficientsYUVA420 { } sourcePlane.data.withUnsafeBytes { sourceBytes in - let coefficients = sourceBytes.baseAddress!.assumingMemoryBound(to: UInt16.self) + let coefficients = sourceBytes.baseAddress!.assumingMemoryBound(to: Int16.self) targetPlane.data.withUnsafeMutableBytes { bytes in let pixels = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self) From 31e1f7328b5542b487103aefd3c9fa769effe36d Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 30 Jun 2022 18:50:05 +0300 Subject: [PATCH 021/113] Add account deletion logging --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/InviteLinkHeaderItem.swift | 7 ++- .../Sources/DeleteAccountDataController.swift | 51 +++++++++++++++++-- .../DeleteAccountOptionsController.swift | 28 +++++++++- .../Sources/DeleteAccountPeersItem.swift | 10 +--- .../Themes/ThemeSettingsController.swift | 2 +- 6 files changed, 84 insertions(+), 16 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 6a132802cb..e5e3bbfce5 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7797,6 +7797,8 @@ Sorry for the inconvenience."; "DeleteAccount.ConfirmationAlertText" = "Deleting your account will permanently delete your data!\n\nIt is imposible to reverse this action!"; "DeleteAccount.ConfirmationAlertDelete" = "Delete My Account"; +"DeleteAccount.Success" = "The account has been successfully deleted."; + "PeerInfo.GiftPremium" = "Gift Premium"; "Premium.Gift.Title" = "Gift Telegram Premium"; diff --git a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift index e5bdbe1cde..2eb83c529a 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift @@ -114,7 +114,12 @@ class InviteLinkHeaderItemNode: ListViewItemNode { return { item, params, neighbors in let leftInset: CGFloat = 24.0 + params.leftInset - let iconSize = CGSize(width: 140.0, height: 140.0) + let iconSize: CGSize + if params.width > params.availableHeight && params.width > 320.0 { + iconSize = CGSize(width: 140.0, height: 140.0) + } else { + iconSize = CGSize(width: 124.0, height: 124.0) + } let topInset: CGFloat = iconSize.height - 4.0 let spacing: CGFloat = 5.0 diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index 04be040592..76a1bca8fd 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -15,6 +15,7 @@ import UrlHandling import InviteLinksUI import CountrySelectionUI import PhoneInputNode +import UndoUI private struct DeleteAccountDataArguments { let context: AccountContext @@ -289,6 +290,23 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat peers = .single([]) } + let cancelImpl = { + dismissImpl?() + + switch mode { + case .peers: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_cloud_cancel") + case .groups: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_groups_cancel") + case .messages: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_messages_cancel") + case .phone: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_phone_cancel") + case .password: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_2fa_cancel") + } + } + let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, peers, @@ -296,7 +314,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat ) |> map { presentationData, peers, state -> (ItemListControllerState, (ItemListNodeState, Any)) in let leftNavigationButton = ItemListNavigationButton(content: .text(presentationData.strings.Common_Cancel), style: .regular, enabled: true, action: { - dismissImpl?() + cancelImpl() }) var focusItemTag: DeleteAccountEntryTag? @@ -319,7 +337,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat } let footerItem = DeleteAccountFooterItem(theme: presentationData.theme, title: buttonTitle, secondaryTitle: presentationData.strings.DeleteAccount_Continue, action: { - dismissImpl?() + cancelImpl() }, secondaryAction: { proceedImpl?() }) @@ -414,7 +432,13 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let controller = deleteAccountDataController(context: context, mode: nextMode, twoStepAuthData: twoStepAuthData) replaceTopControllerImpl?(controller) } else { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_show") + presentControllerImpl?(textAlertController(context: context, title: presentationData.strings.DeleteAccount_ConfirmationAlertTitle, text: presentationData.strings.DeleteAccount_ConfirmationAlertText, actions: [TextAlertAction(type: .destructiveAction, title: presentationData.strings.DeleteAccount_ConfirmationAlertDelete, action: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.final") + + invokeAppLogEventsSynchronization(postbox: context.account.postbox) + updateState { current in var updated = current updated.isLoading = true @@ -434,9 +458,17 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])) }, completed: { dismissImpl?() - let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: true).start() + + let presentGlobalController = context.sharedContext.presentGlobalController + let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: true).start(completed: { + Queue.mainQueue().after(0.1) { + presentGlobalController(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.DeleteAccount_Success), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) + } + }) }) }), TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_Cancel, action: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_confirmation_cancel") + dismissImpl?() })])) } @@ -517,6 +549,19 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat } } + switch mode { + case .peers: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_cloud_show") + case .groups: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_groups_show") + case .messages: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_messages_show") + case .phone: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_phone_show") + case .password: + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.step_2fa_show") + } + return controller } diff --git a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift index bc3d7f50e1..24d4cb6225 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountOptionsController.swift @@ -180,6 +180,8 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo let supportPeerDisposable = MetaDisposable() let arguments = DeleteAccountOptionsArguments(changePhoneNumber: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_phone_change_tap") + let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: context.engine.account.peerId)) |> deliverOnMainQueue).start(next: { accountPeer in guard let accountPeer = accountPeer, case let .user(user) = accountPeer else { @@ -192,6 +194,8 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo dismissImpl?() }) }, addAccount: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_add_account_tap") + let _ = (activeAccountsAndPeers(context: context) |> take(1) |> deliverOnMainQueue @@ -227,8 +231,12 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo } }) }, setupPrivacy: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_privacy_tap") + replaceTopControllerImpl?(makePrivacyAndSecurityController(context: context), false) }, setupTwoStepAuth: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_2fa_tap") + if let data = twoStepAuthData { switch data { case .set: @@ -252,6 +260,8 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo let controller = twoStepVerificationUnlockSettingsController(context: context, mode: .access(intro: false, data: twoStepAuthData.flatMap({ Signal.single(.access(configuration: $0)) }))) replaceTopControllerImpl?(controller, false) }, setPasscode: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_passcode_tap") + let _ = passcodeOptionsAccessController(context: context, pushController: { controller in replaceTopControllerImpl?(controller, false) }, completion: { _ in @@ -263,11 +273,17 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo }) dismissImpl?() }, clearCache: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_cache_tap") + pushControllerImpl?(storageUsageController(context: context)) dismissImpl?() }, clearSyncedContacts: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_clear_contacts_tap") + replaceTopControllerImpl?(dataPrivacyController(context: context), false) }, deleteChats: { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_delete_chats_tap") + let presentationData = context.sharedContext.currentPresentationData.with { $0 } var faqUrl = presentationData.strings.DeleteAccount_DeleteMessagesURL @@ -298,6 +314,8 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo openFaq(resolvedUrlPromise) }, contactSupport: { [weak navigationController] in + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_support_tap") + let presentationData = context.sharedContext.currentPresentationData.with { $0 } let supportPeer = Promise() @@ -329,7 +347,7 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo }) } - presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Settings_FAQ_Intro, actions: [ + let alertController = textAlertController(context: context, title: nil, text: presentationData.strings.Settings_FAQ_Intro, actions: [ TextAlertAction(type: .genericAction, title: presentationData.strings.Settings_FAQ_Button, action: { openFaq(resolvedUrlPromise) dismissImpl?() @@ -344,7 +362,11 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo } })) }) - ]), nil) + ]) + alertController.dismissed = { + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_support_cancel") + } + presentControllerImpl?(alertController, nil) }, deleteAccount: { let controller = deleteAccountDataController(context: context, mode: .peers, twoStepAuthData: twoStepAuthData) replaceTopControllerImpl?(controller, true) @@ -411,6 +433,8 @@ public func deleteAccountOptionsController(context: AccountContext, navigationCo dismissImpl = { [weak controller] in let _ = controller?.dismiss() } + + addAppLogEvent(postbox: context.account.postbox, type: "deactivate.options_show") return controller } diff --git a/submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift b/submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift index f5c1b34c52..48df82976f 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountPeersItem.swift @@ -201,15 +201,7 @@ class DeleteAccountPeersItemNode: ListViewItemNode, ItemListItemNode { } func asyncLayout() -> (_ item: DeleteAccountPeersItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { - let currentItem = self.item - - return { item, params, neighbors in - var themeUpdated = false - if currentItem?.theme !== item.theme { - themeUpdated = true - } - print(themeUpdated) - + return { item, params, neighbors in let contentSize: CGSize var insets: UIEdgeInsets let separatorHeight = UIScreenPixel diff --git a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift index 38403b25a6..c5f815fe6e 100644 --- a/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift +++ b/submodules/SettingsUI/Sources/Themes/ThemeSettingsController.swift @@ -424,7 +424,7 @@ public func themeSettingsController(context: AccountContext, focusOnItemTag: The } let premiumConfiguration = PremiumConfiguration.with(appConfiguration: context.currentAppConfiguration.with { $0 }) - if premiumConfiguration.isPremiumDisabled { + if premiumConfiguration.isPremiumDisabled || context.account.testingEnvironment { appIcons = appIcons.filter { !$0.isPremium } } From 6933a189a49e720c7c70d69980d691c4823fb9c0 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 30 Jun 2022 22:45:10 +0300 Subject: [PATCH 022/113] Add deletion search shortcut --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/Search/SettingsSearchItem.swift | 18 +++++--- .../Search/SettingsSearchableItems.swift | 41 ++++++++----------- .../PresentationResourcesSettings.swift | 2 + .../Sources/PeerInfo/PeerInfoScreen.swift | 7 +++- 5 files changed, 40 insertions(+), 30 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e5e3bbfce5..c3490ef264 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7818,3 +7818,5 @@ Sorry for the inconvenience."; "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."; + +"SettingsSearch.DeleteAccount.DeleteMyAccount" = " "; diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift index 71638b64a4..2f671c912a 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchItem.swift @@ -49,6 +49,8 @@ extension SettingsSearchableItemIcon { return PresentationResourcesSettings.faq case .chatFolders: return PresentationResourcesSettings.chatFolders + case .deleteAccount: + return PresentationResourcesSettings.deleteAccount } } } @@ -67,6 +69,7 @@ final class SettingsSearchItem: ItemListControllerSearch { let archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError> let privacySettings: Signal let hasTwoStepAuth: Signal + let twoStepAuthData: Signal let activeSessionsContext: Signal let webSessionsContext: Signal @@ -74,7 +77,7 @@ final class SettingsSearchItem: ItemListControllerSearch { private var activity: ValuePromise = ValuePromise(ignoreRepeated: false) private let activityDisposable = MetaDisposable() - init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, getNavigationController: (() -> NavigationController?)?, resolvedFaqUrl: Signal, exceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) { + init(context: AccountContext, theme: PresentationTheme, placeholder: String, activated: Bool, updateActivated: @escaping (Bool) -> Void, presentController: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, getNavigationController: (() -> NavigationController?)?, resolvedFaqUrl: Signal, exceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, twoStepAuthData: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) { self.context = context self.theme = theme self.placeholder = placeholder @@ -88,6 +91,7 @@ final class SettingsSearchItem: ItemListControllerSearch { self.archivedStickerPacks = archivedStickerPacks self.privacySettings = privacySettings self.hasTwoStepAuth = hasTwoStepAuth + self.twoStepAuthData = twoStepAuthData self.activeSessionsContext = activeSessionsContext self.webSessionsContext = webSessionsContext self.activityDisposable.set((activity.get() |> mapToSignal { value -> Signal in @@ -153,7 +157,7 @@ final class SettingsSearchItem: ItemListControllerSearch { pushController(c) }, presentController: { c, a in presentController(c, a) - }, getNavigationController: self.getNavigationController, resolvedFaqUrl: self.resolvedFaqUrl, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasTwoStepAuth: self.hasTwoStepAuth, activeSessionsContext: self.activeSessionsContext, webSessionsContext: self.webSessionsContext) + }, getNavigationController: self.getNavigationController, resolvedFaqUrl: self.resolvedFaqUrl, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasTwoStepAuth: self.hasTwoStepAuth, twoStepAuthData: self.twoStepAuthData, activeSessionsContext: self.activeSessionsContext, webSessionsContext: self.webSessionsContext) } } } @@ -338,7 +342,7 @@ public final class SettingsSearchContainerNode: SearchDisplayControllerContentNo private var presentationDataDisposable: Disposable? private let presentationDataPromise: Promise - public init(context: AccountContext, openResult: @escaping (SettingsSearchableItem) -> Void, resolvedFaqUrl: Signal, exceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) { + public init(context: AccountContext, openResult: @escaping (SettingsSearchableItem) -> Void, resolvedFaqUrl: Signal, exceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, twoStepAuthData: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) { let presentationData = context.sharedContext.currentPresentationData.with { $0 } self.presentationData = presentationData self.presentationDataPromise = Promise(self.presentationData) @@ -372,7 +376,7 @@ public final class SettingsSearchContainerNode: SearchDisplayControllerContentNo }) let searchableItems = Promise<[SettingsSearchableItem]>() - searchableItems.set(settingsSearchableItems(context: context, notificationExceptionsList: exceptionsList, archivedStickerPacks: archivedStickerPacks, privacySettings: privacySettings, hasTwoStepAuth: hasTwoStepAuth, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext)) + searchableItems.set(settingsSearchableItems(context: context, notificationExceptionsList: exceptionsList, archivedStickerPacks: archivedStickerPacks, privacySettings: privacySettings, hasTwoStepAuth: hasTwoStepAuth, twoStepAuthData: twoStepAuthData, activeSessionsContext: activeSessionsContext, webSessionsContext: webSessionsContext)) let faqItems = Promise<[SettingsSearchableItem]>() faqItems.set(faqSearchableItems(context: context, resolvedUrl: resolvedFaqUrl, suggestAccountDeletion: false)) @@ -646,12 +650,13 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode { let archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError> let privacySettings: Signal let hasTwoStepAuth: Signal + let twoStepAuthData: Signal let activeSessionsContext: Signal let webSessionsContext: Signal var cancel: () -> Void - init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: (() -> NavigationController?)?, resolvedFaqUrl: Signal, exceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) { + init(context: AccountContext, cancel: @escaping () -> Void, updateActivity: @escaping(Bool) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController, Any?) -> Void, getNavigationController: (() -> NavigationController?)?, resolvedFaqUrl: Signal, exceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, twoStepAuthData: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) { self.context = context self.presentationData = context.sharedContext.currentPresentationData.with { $0 } self.cancel = cancel @@ -663,6 +668,7 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode { self.archivedStickerPacks = archivedStickerPacks self.privacySettings = privacySettings self.hasTwoStepAuth = hasTwoStepAuth + self.twoStepAuthData = twoStepAuthData self.activeSessionsContext = activeSessionsContext self.webSessionsContext = webSessionsContext @@ -704,7 +710,7 @@ private final class SettingsSearchItemNode: ItemListControllerSearchNode { } }) } - }, resolvedFaqUrl: self.resolvedFaqUrl, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasTwoStepAuth: self.hasTwoStepAuth, activeSessionsContext: self.activeSessionsContext, webSessionsContext: self.webSessionsContext), cancel: { [weak self] in + }, resolvedFaqUrl: self.resolvedFaqUrl, exceptionsList: self.exceptionsList, archivedStickerPacks: self.archivedStickerPacks, privacySettings: self.privacySettings, hasTwoStepAuth: self.hasTwoStepAuth, twoStepAuthData: self.twoStepAuthData, activeSessionsContext: self.activeSessionsContext, webSessionsContext: self.webSessionsContext), cancel: { [weak self] in self?.cancel() }) diff --git a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift index 1b141cb6c1..3a6ee7ba28 100644 --- a/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift +++ b/submodules/SettingsUI/Sources/Search/SettingsSearchableItems.swift @@ -35,6 +35,7 @@ enum SettingsSearchableItemIcon { case support case faq case chatFolders + case deleteAccount } public enum SettingsSearchableItemId: Hashable { @@ -54,6 +55,7 @@ public enum SettingsSearchableItemId: Hashable { case support(Int32) case faq(Int32) case chatFolders(Int32) + case deleteAccount(Int32) private var namespace: Int32 { switch self { @@ -89,6 +91,8 @@ public enum SettingsSearchableItemId: Hashable { return 15 case .chatFolders: return 16 + case .deleteAccount: + return 17 } } @@ -109,7 +113,8 @@ public enum SettingsSearchableItemId: Hashable { let .wallet(id), let .support(id), let .faq(id), - let .chatFolders(id): + let .chatFolders(id), + let .deleteAccount(id): return id } } @@ -154,6 +159,8 @@ public enum SettingsSearchableItemId: Hashable { self = .faq(id) case 16: self = .chatFolders(id) + case 17: + self = .deleteAccount(id) default: return nil } @@ -338,12 +345,6 @@ private func notificationSearchableItems(context: AccountContext, settings: Glob SettingsSearchableItem(id: .notifications(0), title: strings.Settings_NotificationsAndSounds, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_Title), icon: icon, breadcrumbs: [], present: { context, _, present in presentNotificationSettings(context, present, nil) }), -// SettingsSearchableItem(id: .notifications(1), title: strings.Notifications_MessageNotificationsAlert, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_MessageNotificationsAlert), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications], present: { context, _, present in -// presentNotificationSettings(context, present, .messageAlerts) -// }), -// SettingsSearchableItem(id: .notifications(2), title: strings.Notifications_MessageNotificationsPreview, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_MessageNotificationsPreview), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications], present: { context, _, present in -// presentNotificationSettings(context, present, .messagePreviews) -// }), SettingsSearchableItem(id: .notifications(3), title: strings.Notifications_MessageNotificationsSound, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_MessageNotificationsSound), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications], present: { context, _, present in let controller = notificationSoundSelectionController(context: context, isModal: true, currentSound: filteredGlobalSound(settings.privateChats.sound), defaultSound: nil, completion: { value in @@ -358,12 +359,6 @@ private func notificationSearchableItems(context: AccountContext, settings: Glob SettingsSearchableItem(id: .notifications(4), title: strings.Notifications_MessageNotificationsExceptions, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_MessageNotificationsExceptions), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_MessageNotifications], present: { context, _, present in present(.push, NotificationExceptionsController(context: context, mode: exceptions().0, updatedMode: { _ in})) }), -// SettingsSearchableItem(id: .notifications(5), title: strings.Notifications_GroupNotificationsAlert, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_GroupNotificationsAlert), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications], present: { context, _, present in -// presentNotificationSettings(context, present, .groupAlerts) -// }), -// SettingsSearchableItem(id: .notifications(6), title: strings.Notifications_GroupNotificationsPreview, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_GroupNotificationsPreview), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications], present: { context, _, present in -// presentNotificationSettings(context, present, .groupPreviews) -// }), SettingsSearchableItem(id: .notifications(7), title: strings.Notifications_GroupNotificationsSound, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_GroupNotificationsSound), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications], present: { context, _, present in let controller = notificationSoundSelectionController(context: context, isModal: true, currentSound: filteredGlobalSound(settings.groupChats.sound), defaultSound: nil, completion: { value in let _ = updateGlobalNotificationSettingsInteractively(postbox: context.account.postbox, { settings in @@ -377,12 +372,6 @@ private func notificationSearchableItems(context: AccountContext, settings: Glob SettingsSearchableItem(id: .notifications(8), title: strings.Notifications_GroupNotificationsExceptions, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_GroupNotificationsExceptions), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_GroupNotifications], present: { context, _, present in present(.push, NotificationExceptionsController(context: context, mode: exceptions().1, updatedMode: { _ in})) }), -// SettingsSearchableItem(id: .notifications(9), title: strings.Notifications_ChannelNotificationsAlert, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_ChannelNotificationsAlert), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications], present: { context, _, present in -// presentNotificationSettings(context, present, .channelAlerts) -// }), -// SettingsSearchableItem(id: .notifications(10), title: strings.Notifications_ChannelNotificationsPreview, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_ChannelNotificationsPreview), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications], present: { context, _, present in -// presentNotificationSettings(context, present, .channelPreviews) -// }), SettingsSearchableItem(id: .notifications(11), title: strings.Notifications_ChannelNotificationsSound, alternate: synonyms(strings.SettingsSearch_Synonyms_Notifications_ChannelNotificationsSound), icon: icon, breadcrumbs: [strings.Settings_NotificationsAndSounds, strings.Notifications_ChannelNotifications], present: { context, _, present in let controller = notificationSoundSelectionController(context: context, isModal: true, currentSound: filteredGlobalSound(settings.channels.sound), defaultSound: nil, completion: { value in let _ = updateGlobalNotificationSettingsInteractively(postbox: context.account.postbox, { settings in @@ -735,7 +724,7 @@ private func languageSearchableItems(context: AccountContext, localizations: [Lo return items } -func settingsSearchableItems(context: AccountContext, notificationExceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) -> Signal<[SettingsSearchableItem], NoError> { +func settingsSearchableItems(context: AccountContext, notificationExceptionsList: Signal, archivedStickerPacks: Signal<[ArchivedStickerPackItem]?, NoError>, privacySettings: Signal, hasTwoStepAuth: Signal, twoStepAuthData: Signal, activeSessionsContext: Signal, webSessionsContext: Signal) -> Signal<[SettingsSearchableItem], NoError> { let watchAppInstalled = (context.watchManager?.watchAppInstalled ?? .single(false)) |> take(1) @@ -832,8 +821,8 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList } } - return combineLatest(watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasTwoStepAuth, activeSessionsContext, activeWebSessionsContext) - |> map { watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasTwoStepAuth, activeSessionsContext, activeWebSessionsContext in + return combineLatest(watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasTwoStepAuth, twoStepAuthData, activeSessionsContext, activeWebSessionsContext) + |> map { watchAppInstalled, canAddAccount, localizations, notificationSettings, notificationExceptionsList, archivedStickerPacks, proxyServers, privacySettings, hasTwoStepAuth, twoStepAuthData, activeSessionsContext, activeWebSessionsContext in let strings = context.sharedContext.currentPresentationData.with { $0 }.strings var allItems: [SettingsSearchableItem] = [] @@ -900,7 +889,6 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList allItems.append(support) let faq = SettingsSearchableItem(id: .faq(0), title: strings.Settings_FAQ, alternate: synonyms(strings.SettingsSearch_Synonyms_FAQ), icon: .faq, breadcrumbs: [], present: { context, navigationController, present in - let _ = (cachedFaqInstantPage(context: context) |> deliverOnMainQueue).start(next: { resolvedUrl in context.sharedContext.openResolvedUrl(resolvedUrl, context: context, urlContext: .generic, navigationController: navigationController, forceExternal: false, openPeer: { peer, navigation in @@ -910,6 +898,13 @@ func settingsSearchableItems(context: AccountContext, notificationExceptionsList }) }) allItems.append(faq) + + allItems.append(SettingsSearchableItem(id: .deleteAccount(0), title: strings.DeleteAccount_DeleteMyAccount, alternate: synonyms(strings.SettingsSearch_DeleteAccount_DeleteMyAccount), icon: .deleteAccount, breadcrumbs: [], present: { context, navigationController, present in + if let navigationController = navigationController { + let controller = deleteAccountOptionsController(context: context, navigationController: navigationController, hasTwoStepAuth: hasTwoStepAuth ?? false, twoStepAuthData: twoStepAuthData) + present(.push, controller) + } + })) return allItems } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift index 5910683d1f..0c8679f23b 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesSettings.swift @@ -36,6 +36,8 @@ public struct PresentationResourcesSettings { public static let dataAndStorage = renderIcon(name: "Settings/Menu/DataAndStorage") public static let appearance = renderIcon(name: "Settings/Menu/Appearance") public static let language = renderIcon(name: "Settings/Menu/Language") + + public static let deleteAccount = renderIcon(name: "Chat/Info/GroupRemovedIcon") public static let wallet = generateImage(CGSize(width: 29.0, height: 29.0), contextGenerator: { size, context in let bounds = CGRect(origin: CGPoint(), size: size) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 4fe61f6e60..9cd33f06a7 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -1702,6 +1702,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate private let archivedPacks = Promise<[ArchivedStickerPackItem]?>() private let blockedPeers = Promise(nil) private let hasTwoStepAuth = Promise(nil) + private let twoStepAuthData = Promise(nil) private let hasPassport = Promise(false) private let supportPeerDisposable = MetaDisposable() private let tipsPeerDisposable = MetaDisposable() @@ -2970,6 +2971,10 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate )) self.privacySettings.set(.single(nil) |> then(context.engine.privacy.requestAccountPrivacySettings() |> map(Optional.init))) self.archivedPacks.set(.single(nil) |> then(context.engine.stickers.archivedStickerPacks() |> map(Optional.init))) + self.twoStepAuthData.set(.single(nil) |> then(context.engine.auth.twoStepVerificationConfiguration() + |> map { value -> TwoStepVerificationAccessConfiguration? in + return TwoStepVerificationAccessConfiguration(configuration: value, password: nil) + })) self.hasPassport.set(.single(false) |> then(context.engine.auth.twoStepAuthData() |> map { value -> Bool in return value.hasSecretValues @@ -6763,7 +6768,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } }) } - }, resolvedFaqUrl: self.cachedFaq.get(), exceptionsList: .single(settings.notificationExceptions), archivedStickerPacks: .single(settings.archivedStickerPacks), privacySettings: .single(settings.privacySettings), hasTwoStepAuth: self.hasTwoStepAuth.get(), activeSessionsContext: self.activeSessionsContextAndCount.get() |> map { $0?.0 }, webSessionsContext: self.activeSessionsContextAndCount.get() |> map { $0?.2 }), cancel: { [weak self] in + }, resolvedFaqUrl: self.cachedFaq.get(), exceptionsList: .single(settings.notificationExceptions), archivedStickerPacks: .single(settings.archivedStickerPacks), privacySettings: .single(settings.privacySettings), hasTwoStepAuth: self.hasTwoStepAuth.get(), twoStepAuthData: self.twoStepAuthData.get(), activeSessionsContext: self.activeSessionsContextAndCount.get() |> map { $0?.0 }, webSessionsContext: self.activeSessionsContextAndCount.get() |> map { $0?.2 }), cancel: { [weak self] in self?.deactivateSearch() }) } From 100be3217f36e384636b0193bc0d5a279b41d001 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 1 Jul 2022 23:00:26 +0300 Subject: [PATCH 023/113] Update API --- .../Telegram-iOS/en.lproj/Localizable.strings | 14 + .../Sources/InAppPurchaseManager.swift | 33 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 185 ++++----- .../Sources/PremiumIntroScreen.swift | 116 ++++-- .../Sources/PremiumStarsNode.swift | 78 ++++ .../Sources/ReactionSelectionNode.swift | 69 +--- .../Sources/DeleteAccountDataController.swift | 8 +- submodules/TelegramApi/Sources/Api0.swift | 2 +- submodules/TelegramApi/Sources/Api27.swift | 7 +- submodules/TelegramApi/Sources/Api9.swift | 22 +- .../SyncCore/SyncCore_CachedUserData.swift | 45 ++- .../TelegramEngine/Payments/AppStore.swift | 13 +- .../Peers/UpdateCachedPeerData.swift | 3 +- .../Sources/ServiceMessageStrings.swift | 11 +- .../Components/Gift.imageset/Contents.json | 21 + .../Components/Gift.imageset/gift.png | Bin 0 -> 47754 bytes .../TelegramUI/Sources/ChatController.swift | 6 + .../Sources/ChatMessageBubbleItemNode.swift | 2 + .../Sources/ChatMessageGiftItemNode.swift | 374 ++++++++++++++++++ .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- 20 files changed, 787 insertions(+), 224 deletions(-) create mode 100644 submodules/ReactionSelectionNode/Sources/PremiumStarsNode.swift create mode 100644 submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/gift.png create mode 100644 submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index c3490ef264..f9142b2715 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7814,9 +7814,23 @@ Sorry for the inconvenience."; "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.Title" = "Telegram Premium"; +"Notification.PremiumGift.Subtitle" = "for %@"; +"Notification.PremiumGift.View" = "View"; diff --git a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift index 3ed74340d3..0584b2267c 100644 --- a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift +++ b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift @@ -37,7 +37,7 @@ public final class InAppPurchaseManager: NSObject { } else if #available(iOS 11.2, *) { return self.skProduct.subscriptionPeriod != nil } else { - return !self.id.contains(".monthly") + return self.id.contains(".monthly") } } @@ -89,9 +89,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 } } @@ -120,7 +122,7 @@ public final class InAppPurchaseManager: NSObject { public init(engine: TelegramEngine) { self.engine = engine - + super.init() SKPaymentQueue.default().add(self) @@ -169,10 +171,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)") @@ -186,7 +193,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 { @@ -264,6 +271,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 { @@ -306,8 +316,19 @@ 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 purpose: AppStoreTransactionPurpose + if let productIdentifier = transaction?.payment.productIdentifier, let targetPeerId = paymentContexts[productIdentifier]?.targetPeerId { + purpose = .gift(targetPeerId) + } else { + purpose = .subscription + } + + let receiptData = getReceiptData() ?? Data() self.disposableSet.set( - self.engine.payments.sendAppStoreReceipt(receipt: getReceiptData() ?? Data(), purpose: .subscription).start(error: { [weak self] _ 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 { diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 903c29b49e..2439774bcd 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -752,9 +752,9 @@ private final class PremiumGiftScreenComponent: CombinedComponent { let updateInProgress: (Bool) -> Void let present: (ViewController) -> Void let push: (ViewController) -> Void - let completion: () -> Void + let completion: (Int32) -> Void - init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping () -> Void) { + init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) { self.context = context self.peerId = peerId self.updateInProgress = updateInProgress @@ -778,7 +778,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { private let peerId: PeerId private let updateInProgress: (Bool) -> Void private let present: (ViewController) -> Void - private let completion: () -> Void + private let completion: (Int32) -> Void var topContentOffset: CGFloat? var bottomContentOffset: CGFloat? @@ -795,7 +795,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { private var paymentDisposable = MetaDisposable() private var activationDisposable = MetaDisposable() - init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping () -> Void) { + init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) { self.context = context self.peerId = peerId self.updateInProgress = updateInProgress @@ -844,6 +844,18 @@ private final class PremiumGiftScreenComponent: CombinedComponent { guard let product = self.products?.first(where: { $0.id == self.selectedProductId }) else { return } + + let duration: Int32 + switch product.id { + case "org.telegram.telegramPremium.twelveMonths": + duration = 86400 * 365 + case "org.telegram.telegramPremium.sixMonths": + duration = 86400 * 180 + case "org.telegram.telegramPremium.threeMonths": + duration = 86400 * 90 + default: + duration = 0 + } // addAppLogEvent(postbox: self.context.account.postbox, type: "premium.promo_screen_accept") @@ -851,90 +863,79 @@ private final class PremiumGiftScreenComponent: CombinedComponent { self.updateInProgress(true) self.updated(transition: .immediate) - let _ = (self.context.engine.payments.canPurchasePremium() - |> deliverOnMainQueue).start(next: { [weak self] available in + self.paymentDisposable.set((inAppPurchaseManager.buyProduct(product, targetPeerId: self.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) +// strongSelf.completion(duration) + + 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 { + 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 { - if available { - strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(product) - |> 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) - strongSelf.completion() - - 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 { - let _ = updatePremiumPromoConfigurationOnce(account: strongSelf.context.account).start() - strongSelf.inProgress = false - strongSelf.updateInProgress(false) - - strongSelf.updated(transition: .easeInOut(duration: 0.25)) - strongSelf.completion() - } - })) - } - }, error: { [weak self] error in - if let strongSelf = self { - strongSelf.inProgress = false - strongSelf.updateInProgress(false) - strongSelf.updated(transition: .immediate) + 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) + 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) } } - }) + })) } func updateIsFocused(_ isFocused: Bool) { @@ -1216,7 +1217,7 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { var updateInProgressImpl: ((Bool) -> Void)? var pushImpl: ((ViewController) -> Void)? // var presentImpl: ((ViewController) -> Void)? - var completionImpl: (() -> Void)? + var completionImpl: ((Int32) -> Void)? super.init(context: context, component: PremiumGiftScreenComponent( context: context, peerId: peerId, @@ -1229,8 +1230,8 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { push: { c in pushImpl?(c) }, - completion: { - completionImpl?() + completion: { duration in + completionImpl?(duration) } ), navigationBarAppearance: .transparent) @@ -1256,9 +1257,15 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { self?.push(c) } - completionImpl = { [weak self] in + completionImpl = { [weak self] duration in if let strongSelf = self { - strongSelf.view.addSubview(ConfettiView(frame: strongSelf.view.bounds)) + let navigationController = strongSelf.navigationController + strongSelf.dismiss() + let introController = PremiumIntroScreen(context: context, source: .gift(from: context.account.peerId, to: peerId, duration: duration)) + navigationController?.pushViewController(introController, animated: true) + Queue.mainQueue().after(0.1, { + introController.view.addSubview(ConfettiView(frame: introController.view.bounds)) + }) } } } diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index c62048a366..0dcb18a9b6 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -38,8 +38,9 @@ public enum PremiumSource: Equatable { case appIcons case deeplink(String?) case profile(PeerId) + case gift(from: PeerId, to: PeerId, duration: Int32) - var identifier: String { + var identifier: String? { switch self { case .settings: return "settings" @@ -73,6 +74,8 @@ public enum PremiumSource: Equatable { return "double_limits__about" case let .profile(id): return "profile__\(id.id._internalGetInt64Value())" + case .gift: + return nil case let .deeplink(reference): if let reference = reference { return "deeplink_\(reference)" @@ -695,22 +698,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 { @@ -815,7 +820,15 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { let textString: String if let _ = context.component.otherPeerName { - textString = strings.Premium_PersonalDescription + 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 { @@ -1036,8 +1049,17 @@ 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 { + 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) termsString = .plain(attributedString) } else { @@ -1229,7 +1251,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 @@ -1418,7 +1447,9 @@ private final class PremiumIntroScreenComponent: CombinedComponent { ) let titleString: String - if state.isPremium == true { + 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 @@ -1444,9 +1475,43 @@ 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 >= 86400 * 365 { + secondaryTitleText = environment.strings.Premium_GiftedTitleYou_12Month(otherPeerName).string + } else if duration >= 86400 * 180 { + secondaryTitleText = environment.strings.Premium_GiftedTitleYou_6Month(otherPeerName).string + } else if duration >= 86400 * 90 { + secondaryTitleText = environment.strings.Premium_GiftedTitleYou_3Month(otherPeerName).string + } else { + secondaryTitleText = "" + } + } else { + if duration >= 86400 * 365 { + secondaryTitleText = environment.strings.Premium_GiftedTitle_12Month(otherPeerName).string + } else if duration >= 86400 * 180 { + secondaryTitleText = environment.strings.Premium_GiftedTitle_6Month(otherPeerName).string + } else if duration >= 86400 * 90 { + 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, @@ -1557,8 +1622,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/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/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index 76a1bca8fd..2af68895fd 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -307,6 +307,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat } } + var secondaryActionDisabled = false let signal = combineLatest(queue: .mainQueue(), context.sharedContext.presentationData, peers, @@ -339,7 +340,10 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let footerItem = DeleteAccountFooterItem(theme: presentationData.theme, title: buttonTitle, secondaryTitle: presentationData.strings.DeleteAccount_Continue, action: { cancelImpl() }, secondaryAction: { - proceedImpl?() + if !secondaryActionDisabled { + secondaryActionDisabled = true + proceedImpl?() + } }) let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(presentationData.strings.DeleteAccount_DeleteMyAccountTitle), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back)) @@ -462,7 +466,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let presentGlobalController = context.sharedContext.presentGlobalController let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: true).start(completed: { Queue.mainQueue().after(0.1) { - presentGlobalController(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.DeleteAccount_Success), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) + presentGlobalController(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.DeleteAccount_Success), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), nil) } }) }) diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 0b6f984df3..45569922f5 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -348,7 +348,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[70813275] = { return Api.InputStickeredMedia.parse_inputStickeredMediaDocument($0) } dict[1251549527] = { return Api.InputStickeredMedia.parse_inputStickeredMediaPhoto($0) } dict[1147243133] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentGiftPremium($0) } - dict[-764193027] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumSubscription($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) } diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index 8bf8658194..9b4000c6a8 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -6229,13 +6229,12 @@ public extension Api.functions.messages { } } public extension Api.functions.payments { - static func assignAppStoreTransaction(flags: Int32, receipt: Buffer, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func assignAppStoreTransaction(receipt: Buffer, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(296120783) - serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(-2131921795) serializeBytes(receipt, buffer: buffer, boxed: false) purpose.serialize(buffer, true) - return (FunctionDescription(name: "payments.assignAppStoreTransaction", parameters: [("flags", String(describing: flags)), ("receipt", String(describing: receipt)), ("purpose", String(describing: purpose))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + 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() { diff --git a/submodules/TelegramApi/Sources/Api9.swift b/submodules/TelegramApi/Sources/Api9.swift index 8b493b854d..62718b4098 100644 --- a/submodules/TelegramApi/Sources/Api9.swift +++ b/submodules/TelegramApi/Sources/Api9.swift @@ -457,7 +457,7 @@ public extension Api { public extension Api { enum InputStorePaymentPurpose: TypeConstructorDescription { case inputStorePaymentGiftPremium(userId: Api.InputUser) - case inputStorePaymentPremiumSubscription + case inputStorePaymentPremiumSubscription(flags: Int32) public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { switch self { @@ -467,11 +467,11 @@ public extension Api { } userId.serialize(buffer, true) break - case .inputStorePaymentPremiumSubscription: + case .inputStorePaymentPremiumSubscription(let flags): if boxed { - buffer.appendInt32(-764193027) + buffer.appendInt32(-1502273946) } - + serializeInt32(flags, buffer: buffer, boxed: false) break } } @@ -480,8 +480,8 @@ public extension Api { switch self { case .inputStorePaymentGiftPremium(let userId): return ("inputStorePaymentGiftPremium", [("userId", String(describing: userId))]) - case .inputStorePaymentPremiumSubscription: - return ("inputStorePaymentPremiumSubscription", []) + case .inputStorePaymentPremiumSubscription(let flags): + return ("inputStorePaymentPremiumSubscription", [("flags", String(describing: flags))]) } } @@ -499,7 +499,15 @@ public extension Api { } } public static func parse_inputStorePaymentPremiumSubscription(_ reader: BufferReader) -> InputStorePaymentPurpose? { - return Api.InputStorePaymentPurpose.inputStorePaymentPremiumSubscription + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.InputStorePaymentPurpose.inputStorePaymentPremiumSubscription(flags: _1!) + } + else { + return nil + } } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index 4813cb00b1..865420f7cf 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -64,6 +64,7 @@ public final class CachedUserData: CachedPeerData { public let autoremoveTimeout: CachedPeerAutoremoveTimeout public let themeEmoticon: String? public let photo: TelegramMediaImage? + public let giftPremiumUrl: String? public let peerIds: Set public let messageIds: Set @@ -84,11 +85,12 @@ public final class CachedUserData: CachedPeerData { self.autoremoveTimeout = .unknown self.themeEmoticon = nil self.photo = nil + self.giftPremiumUrl = nil 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?, giftPremiumUrl: String?) { self.about = about self.botInfo = botInfo self.peerStatusSettings = peerStatusSettings @@ -103,6 +105,7 @@ public final class CachedUserData: CachedPeerData { self.autoremoveTimeout = autoremoveTimeout self.themeEmoticon = themeEmoticon self.photo = photo + self.giftPremiumUrl = giftPremiumUrl self.peerIds = Set() @@ -144,6 +147,8 @@ public final class CachedUserData: CachedPeerData { self.photo = nil } + self.giftPremiumUrl = decoder.decodeOptionalStringForKey("gpu") + self.peerIds = Set() var messageIds = Set() @@ -197,6 +202,12 @@ public final class CachedUserData: CachedPeerData { } else { encoder.encodeNil(forKey: "ph") } + + if let giftPremiumUrl = self.giftPremiumUrl, !giftPremiumUrl.isEmpty { + encoder.encodeString(giftPremiumUrl, forKey: "gpu") + } else { + encoder.encodeNil(forKey: "gpu") + } } public func isEqual(to: CachedPeerData) -> Bool { @@ -215,58 +226,62 @@ public final class CachedUserData: CachedPeerData { } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) } 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, giftPremiumUrl: self.giftPremiumUrl) + } + + public func withUpdatedGiftPremiumUrl(_ giftPremiumUrl: 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: self.themeEmoticon, photo: self.photo, giftPremiumUrl: giftPremiumUrl) } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index 5f3a8d57a3..3ac874fe5d 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -17,15 +17,14 @@ public enum AppStoreTransactionPurpose { } func _internal_sendAppStoreReceipt(account: Account, receipt: Data, purpose: AppStoreTransactionPurpose) -> Signal { - var flags: Int32 = 0 - if case .restore = purpose { - flags |= (1 << 0) - } - var purposeSignal: Signal switch purpose { case .subscription, .restore: - purposeSignal = .single(.inputStorePaymentPremiumSubscription) + var flags: Int32 = 0 + if case .restore = purpose { + flags |= (1 << 0) + } + purposeSignal = .single(.inputStorePaymentPremiumSubscription(flags: flags)) case let .gift(peerId): purposeSignal = account.postbox.loadedPeerWithId(peerId) |> mapToSignal { peer -> Signal in @@ -40,7 +39,7 @@ func _internal_sendAppStoreReceipt(account: Account, receipt: Data, purpose: App return purposeSignal |> castError(AssignAppStoreTransactionError.self) |> mapToSignal { purpose -> Signal in - return account.network.request(Api.functions.payments.assignAppStoreTransaction(flags: flags, receipt: Buffer(data: receipt), purpose: purpose)) + return account.network.request(Api.functions.payments.assignAppStoreTransaction(receipt: Buffer(data: receipt), purpose: purpose)) |> mapError { error -> AssignAppStoreTransactionError in if error.errorCode == 406 { return .serverProvided diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 511c198288..7aa4e71284 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -234,7 +234,7 @@ 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, _, _, _, giftPremiumUrl): let botInfo = userFullBotInfo.flatMap(BotInfo.init(apiBotInfo:)) let isBlocked = (userFullFlags & (1 << 0)) != 0 let voiceCallsAvailable = (userFullFlags & (1 << 4)) != 0 @@ -256,6 +256,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee .withUpdatedAutoremoveTimeout(autoremoveTimeout) .withUpdatedThemeEmoticon(userFullThemeEmoticon) .withUpdatedPhoto(photo) + .withUpdatedGiftPremiumUrl(giftPremiumUrl) } }) } diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 19804dd893..e9ca6c3d49 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -652,8 +652,15 @@ public func universalServiceMessageString(presentationData: (PresentationTheme, } case let .webViewData(text): attributedString = NSAttributedString(string: strings.Notification_WebAppSentData(text).string, font: titleFont, textColor: primaryTextColor) - case .giftPremium: - attributedString = nil + 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/Images.xcassets/Components/Gift.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/Contents.json new file mode 100644 index 0000000000..74c463b66f --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "gift.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/gift.png b/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/gift.png new file mode 100644 index 0000000000000000000000000000000000000000..a31babda90031ee20a4069c04bdafb257dd25042 GIT binary patch literal 47754 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 ([ 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))) } diff --git a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift new file mode 100644 index 0000000000..db3f927777 --- /dev/null +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -0,0 +1,374 @@ +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 + +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 giftNode: ASImageNode + + private let buttonNode: HighlightTrackingButtonNode + private let buttonStarsNode: PremiumStarsNode + private let buttonTitleNode: TextNode + + private var cachedMaskBackgroundImage: (CGPoint, UIImage, [CGRect])? + private var absoluteRect: (CGRect, CGSize)? + + 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.giftNode = ASImageNode() + self.giftNode.isUserInteractionEnabled = false + self.giftNode.displaysAsynchronously = false + + 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.giftNode) + + 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 imageSize = CGSize(width: 220.0, height: 210.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 = "" + for media in item.message.media { + if let action = media as? TelegramMediaAction { + switch action.action { + case let .giftPremium(_, _, durationValue): + duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(timeIntervalString(strings: item.presentationData.strings, value: durationValue)).string + 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: imageSize.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: imageSize.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: imageSize.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 + imageSize.height + 18.0) + + return (backgroundSize.width, { boundingWidth in + return (backgroundSize, { [weak self] animation, synchronousLoads, _ in + if let strongSelf = self { + strongSelf.item = item + + strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) + + let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: labelLayout.size.height + 16.0), size: imageSize) + 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) + + strongSelf.giftNode.image = UIImage(bundleImageName: "Components/Gift") + if let image = strongSelf.giftNode.image { + strongSelf.giftNode.frame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - image.size.width) / 2.0), y: mediaBackgroundFrame.minY + 14.0), size: image.size) + } + + 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 + 121.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 + } + } +} diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 9cd33f06a7..6672db95ca 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -4059,7 +4059,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }))) } - if !user.isDeleted && user.botInfo == nil && !user.flags.contains(.isSupport) { + if !user.isDeleted && user.botInfo == nil && !user.flags.contains(.isSupport), let cachedData = data.cachedData as? CachedUserData, let _ = cachedData.giftPremiumUrl { 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 From c71400eab8419846f38d198f6fab91108cb5143d Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 1 Jul 2022 23:51:10 +0300 Subject: [PATCH 024/113] Fix photo rescale for large images --- submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m index fb3493ab30..86298a2ac5 100644 --- a/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m +++ b/submodules/LegacyComponents/Sources/TGPhotoEditorUtils.m @@ -130,7 +130,7 @@ CGImageRef TGPhotoLanczosResize(UIImage *image, CGSize targetSize) NSUInteger bytesPerPixel = 4; NSUInteger dstBytesPerRow = bytesPerPixel * (NSUInteger)targetSize.width; - uint8_t *dstData = (uint8_t *)calloc((NSUInteger)targetSize.height * (NSInteger)targetSize.width * bytesPerPixel, sizeof(uint8_t)); + uint8_t *dstData = (uint8_t *)calloc((NSUInteger)targetSize.height * (NSUInteger)dstBytesPerRow, sizeof(uint8_t)); vImage_Buffer dstBuffer = { .data = dstData, @@ -139,7 +139,11 @@ CGImageRef TGPhotoLanczosResize(UIImage *image, CGSize targetSize) .rowBytes = dstBytesPerRow }; - ret = vImageScale_ARGB8888(&srcBuffer, &dstBuffer, NULL, kvImageHighQualityResampling); + vImage_Flags flags = kvImageHighQualityResampling; + if (MAX(image.size.width, image.size.height) > 4200) { + flags = kvImageNoFlags; + } + ret = vImageScale_ARGB8888(&srcBuffer, &dstBuffer, NULL, flags); free(srcBuffer.data); if (ret != kvImageNoError) { From 087bf3352e07b7d97dd65afc94d92f7d3173b1d3 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 2 Jul 2022 00:04:43 +0200 Subject: [PATCH 025/113] Sticker input rewrite continued --- .../Source/Base/Transition.swift | 16 +- .../Source/Host/ComponentHostView.swift | 90 +++++++ .../Source/Utils/ActionSlot.swift | 2 +- .../Sources/PagerComponent.swift | 216 ++++++++++++---- .../ContainedViewLayoutTransition.swift | 22 ++ .../Display/Source/GridNodeScroller.swift | 12 +- .../Sources/AnimationCache.swift | 2 +- .../Components/ChatInputPanelContainer/BUILD | 1 + .../Sources/ChatInputPanelContainer.swift | 180 +++++++++++-- .../Sources/EmojiPagerContentComponent.swift | 123 +++++++-- .../Sources/EntityKeyboard.swift | 242 ++++++++++++++++-- .../EntityKeyboardBottomPanelComponent.swift | 68 ++++- ...tyKeyboardTopContainerPanelComponent.swift | 69 ++++- .../EntityKeyboardTopPanelComponent.swift | 87 ++++++- .../EntitySearchContentComponent.swift | 118 +++++++++ .../Sources/GifPagerContentComponent.swift | 6 +- .../Sources/MultiAnimationRenderer.swift | 12 - .../TelegramUI/Sources/ChatController.swift | 7 +- .../Sources/ChatControllerNode.swift | 91 +++++-- .../Sources/ChatEntityKeyboardInputNode.swift | 105 +++++++- .../TelegramUI/Sources/ChatInputNode.swift | 3 + .../Sources/ChatTextInputPanelNode.swift | 4 +- .../Sources/PaneSearchContainerNode.swift | 10 +- 23 files changed, 1299 insertions(+), 187 deletions(-) create mode 100644 submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index a57d781e9d..ecfc9ec761 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -192,14 +192,17 @@ 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.layer.presentation()?.position ?? view.center let previousBounds = view.layer.presentation()?.bounds ?? view.bounds - 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) @@ -293,12 +296,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, diff --git a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift index 3c4698a38e..bd29143893 100644 --- a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift +++ b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift @@ -118,3 +118,93 @@ 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 transition.userData(ComponentHostViewSkipSettingFrame.self) == nil { + transition.setFrame(view: componentView, frame: CGRect(origin: CGPoint(), size: updatedSize)) + } + + 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/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index c24f6a728b..040f784ca4 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -3,19 +3,31 @@ import UIKit import Display import ComponentFlow +public protocol PagerExpandableScrollView: UIScrollView { +} + +public protocol PagerPanGestureRecognizer: UIGestureRecognizer { +} + public final class PagerComponentChildEnvironment: Equatable { public struct ContentScrollingUpdate { public var relativeOffset: CGFloat - public var absoluteOffsetToClosestEdge: CGFloat? + public var absoluteOffsetToTopEdge: CGFloat? + public var absoluteOffsetToBottomEdge: CGFloat? + public var isInteracting: Bool public var transition: Transition public init( relativeOffset: CGFloat, - absoluteOffsetToClosestEdge: CGFloat?, + absoluteOffsetToTopEdge: CGFloat?, + absoluteOffsetToBottomEdge: CGFloat?, + isInteracting: Bool, transition: Transition ) { self.relativeOffset = relativeOffset - self.absoluteOffsetToClosestEdge = absoluteOffsetToClosestEdge + self.absoluteOffsetToTopEdge = absoluteOffsetToTopEdge + self.absoluteOffsetToBottomEdge = absoluteOffsetToBottomEdge + self.isInteracting = isInteracting self.transition = transition } } @@ -40,28 +52,34 @@ public final class PagerComponentChildEnvironment: Equatable { } } -public final class PagerComponentPanelEnvironment: Equatable { +public final class PagerComponentPanelEnvironment: Equatable { public let contentOffset: CGFloat - public let contentTopPanels: [AnyComponentWithIdentity] + public let contentTopPanels: [AnyComponentWithIdentity] public let contentIcons: [AnyComponentWithIdentity] + public let contentAccessoryLeftButtons: [AnyComponentWithIdentity] public let contentAccessoryRightButtons: [AnyComponentWithIdentity] public let activeContentId: AnyHashable? public let navigateToContentId: (AnyHashable) -> Void + public let visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> init( contentOffset: CGFloat, - contentTopPanels: [AnyComponentWithIdentity], + contentTopPanels: [AnyComponentWithIdentity], contentIcons: [AnyComponentWithIdentity], + contentAccessoryLeftButtons: [AnyComponentWithIdentity], contentAccessoryRightButtons: [AnyComponentWithIdentity], activeContentId: AnyHashable?, - navigateToContentId: @escaping (AnyHashable) -> Void + navigateToContentId: @escaping (AnyHashable) -> Void, + visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> ) { self.contentOffset = contentOffset self.contentTopPanels = contentTopPanels self.contentIcons = contentIcons + self.contentAccessoryLeftButtons = contentAccessoryLeftButtons self.contentAccessoryRightButtons = contentAccessoryRightButtons self.activeContentId = activeContentId self.navigateToContentId = navigateToContentId + self.visibilityFractionUpdated = visibilityFractionUpdated } public static func ==(lhs: PagerComponentPanelEnvironment, rhs: PagerComponentPanelEnvironment) -> Bool { @@ -74,12 +92,18 @@ public final class PagerComponentPanelEnvironment: Equatable { 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 } @@ -93,38 +117,48 @@ public struct PagerComponentPanelState { } } -public final class PagerComponent: Component { +public final class PagerComponentViewTag { + public init() { + } +} + +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 contentTopPanels: [AnyComponentWithIdentity] public let contentIcons: [AnyComponentWithIdentity] + public let contentAccessoryLeftButtons:[AnyComponentWithIdentity] public let contentAccessoryRightButtons:[AnyComponentWithIdentity] public let defaultId: AnyHashable? public let contentBackground: AnyComponent? - public let topPanel: AnyComponent? + public let topPanel: AnyComponent>? public let externalTopPanelContainer: UIView? - public let bottomPanel: AnyComponent? + public let bottomPanel: AnyComponent>? public let panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)? + public let hidePanels: Bool public init( contentInsets: UIEdgeInsets, contents: [AnyComponentWithIdentity<(ChildEnvironmentType, PagerComponentChildEnvironment)>], - contentTopPanels: [AnyComponentWithIdentity], + contentTopPanels: [AnyComponentWithIdentity], contentIcons: [AnyComponentWithIdentity], - contentAccessoryRightButtons:[AnyComponentWithIdentity], + contentAccessoryLeftButtons: [AnyComponentWithIdentity], + contentAccessoryRightButtons: [AnyComponentWithIdentity], defaultId: AnyHashable?, contentBackground: AnyComponent?, - topPanel: AnyComponent?, + topPanel: AnyComponent>?, externalTopPanelContainer: UIView?, - bottomPanel: AnyComponent?, - panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)? + bottomPanel: AnyComponent>?, + panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)?, + hidePanels: Bool ) { self.contentInsets = contentInsets self.contents = contents self.contentTopPanels = contentTopPanels self.contentIcons = contentIcons + self.contentAccessoryLeftButtons = contentAccessoryLeftButtons self.contentAccessoryRightButtons = contentAccessoryRightButtons self.defaultId = defaultId self.contentBackground = contentBackground @@ -132,6 +166,7 @@ public final class PagerComponent: Component { self.externalTopPanelContainer = externalTopPanelContainer self.bottomPanel = bottomPanel self.panelStateUpdated = panelStateUpdated + self.hidePanels = hidePanels } public static func ==(lhs: PagerComponent, rhs: PagerComponent) -> Bool { @@ -162,43 +197,56 @@ public final class PagerComponent: Component { if lhs.bottomPanel != rhs.bottomPanel { return false } + if lhs.hidePanels != rhs.hidePanels { + return false + } return true } - public final class View: UIView { + public final class View: UIView, ComponentTaggedView { private final class ContentView { let view: ComponentHostView<(ChildEnvironmentType, PagerComponentChildEnvironment)> - var scrollingPanelOffsetToClosestEdge: CGFloat = 0.0 + 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 var topPanelView: ComponentHostView? - private var bottomPanelView: ComponentHostView? + private let topPanelVisibilityFractionUpdated = ActionSlot<(CGFloat, Transition)>() + private var topPanelView: ComponentHostView>? + private let bottomPanelVisibilityFractionUpdated = ActionSlot<(CGFloat, Transition)>() + private var bottomPanelView: ComponentHostView>? - private var centralId: AnyHashable? + private var topPanelHeight: CGFloat? + private var bottomPanelHeight: CGFloat? + + public private(set) var centralId: AnyHashable? private var paneTransitionGestureState: PaneTransitionGestureState? - private var component: PagerComponent? + private var component: PagerComponent? private weak var state: EmptyComponentState? - private var panRecognizer: UIPanGestureRecognizer? + private var panRecognizer: PagerPanGestureRecognizerImpl? override init(frame: CGRect) { super.init(frame: frame) self.disablesInteractiveTransitionGestureRecognizer = true - let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) + let panRecognizer = PagerPanGestureRecognizerImpl(target: self, action: #selector(self.panGesture(_:))) self.panRecognizer = panRecognizer self.addGestureRecognizer(panRecognizer) } @@ -207,6 +255,14 @@ public final class PagerComponent: Component { 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: @@ -252,7 +308,7 @@ public final class PagerComponent: Component { } } - func update(component: PagerComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + func update(component: PagerComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { self.component = component self.state = state @@ -288,22 +344,22 @@ public final class PagerComponent: Component { var contentInsets = component.contentInsets - let scrollingPanelOffsetToClosestEdge: CGFloat + var scrollingPanelOffsetFraction: CGFloat if let centralId = centralId, let centralContentView = self.contentViews[centralId] { - scrollingPanelOffsetToClosestEdge = centralContentView.scrollingPanelOffsetToClosestEdge + scrollingPanelOffsetFraction = centralContentView.scrollingPanelOffsetFraction } else { - scrollingPanelOffsetToClosestEdge = 0.0 + scrollingPanelOffsetFraction = 0.0 } var topPanelHeight: CGFloat = 0.0 if let topPanel = component.topPanel { - let topPanelView: ComponentHostView + let topPanelView: ComponentHostView> var topPanelTransition = transition if let current = self.topPanelView { topPanelView = current } else { topPanelTransition = .immediate - topPanelView = ComponentHostView() + topPanelView = ComponentHostView>() topPanelView.clipsToBounds = true self.topPanelView = topPanelView } @@ -321,20 +377,38 @@ public final class PagerComponent: Component { contentOffset: 0.0, contentTopPanels: component.contentTopPanels, contentIcons: [], + contentAccessoryLeftButtons: [], contentAccessoryRightButtons: [], activeContentId: centralId, - navigateToContentId: navigateToContentId + navigateToContentId: navigateToContentId, + visibilityFractionUpdated: self.topPanelVisibilityFractionUpdated ) }, containerSize: availableSize ) - let topPanelOffset = max(0.0, min(topPanelSize.height, scrollingPanelOffsetToClosestEdge)) + self.topPanelHeight = topPanelSize.height + + var topPanelOffset = topPanelSize.height * scrollingPanelOffsetFraction + + var topPanelVisibilityFraction: CGFloat = 1.0 - scrollingPanelOffsetFraction + if component.hidePanels { + topPanelVisibilityFraction = 0.0 + } + + self.topPanelVisibilityFractionUpdated.invoke((topPanelVisibilityFraction, topPanelTransition)) topPanelHeight = max(0.0, topPanelSize.height - topPanelOffset) + if component.hidePanels { + topPanelOffset = topPanelSize.height + } + if component.externalTopPanelContainer != nil { - let visibleTopPanelHeight = max(0.0, topPanelSize.height - topPanelOffset) + var visibleTopPanelHeight = max(0.0, topPanelSize.height - topPanelOffset) + if component.hidePanels { + visibleTopPanelHeight = 0.0 + } transition.setFrame(view: topPanelView, frame: CGRect(origin: CGPoint(), size: CGSize(width: topPanelSize.width, height: visibleTopPanelHeight))) } else { transition.setFrame(view: topPanelView, frame: CGRect(origin: CGPoint(x: 0.0, y: -topPanelOffset), size: topPanelSize)) @@ -342,22 +416,24 @@ public final class PagerComponent: Component { contentInsets.top += topPanelSize.height } else { - if let bottomPanelView = self.bottomPanelView { - self.bottomPanelView = nil + if let topPanelView = self.topPanelView { + self.topPanelView = nil - bottomPanelView.removeFromSuperview() + topPanelView.removeFromSuperview() } + + self.topPanelHeight = 0.0 } var bottomPanelOffset: CGFloat = 0.0 if let bottomPanel = component.bottomPanel { - let bottomPanelView: ComponentHostView + let bottomPanelView: ComponentHostView> var bottomPanelTransition = transition if let current = self.bottomPanelView { bottomPanelView = current } else { bottomPanelTransition = .immediate - bottomPanelView = ComponentHostView() + bottomPanelView = ComponentHostView>() self.bottomPanelView = bottomPanelView self.addSubview(bottomPanelView) } @@ -365,19 +441,26 @@ public final class PagerComponent: Component { transition: bottomPanelTransition, component: bottomPanel, environment: { - PagerComponentPanelEnvironment( + PagerComponentPanelEnvironment( contentOffset: 0.0, contentTopPanels: [], contentIcons: component.contentIcons, + contentAccessoryLeftButtons: component.contentAccessoryLeftButtons, contentAccessoryRightButtons: component.contentAccessoryRightButtons, activeContentId: centralId, - navigateToContentId: navigateToContentId + navigateToContentId: navigateToContentId, + visibilityFractionUpdated: self.bottomPanelVisibilityFractionUpdated ) }, containerSize: availableSize ) - bottomPanelOffset = max(0.0, min(bottomPanelSize.height, scrollingPanelOffsetToClosestEdge)) + self.bottomPanelHeight = bottomPanelSize.height + + bottomPanelOffset = bottomPanelSize.height * scrollingPanelOffsetFraction + if component.hidePanels { + bottomPanelOffset = bottomPanelSize.height + } transition.setFrame(view: bottomPanelView, frame: CGRect(origin: CGPoint(x: 0.0, y: availableSize.height - bottomPanelSize.height + bottomPanelOffset), size: bottomPanelSize)) @@ -388,8 +471,12 @@ public final class PagerComponent: Component { bottomPanelView.removeFromSuperview() } + + self.bottomPanelHeight = 0.0 } + let effectiveTopPanelHeight: CGFloat = component.hidePanels ? 0.0 : topPanelHeight + if let contentBackground = component.contentBackground { let contentBackgroundView: ComponentHostView var contentBackgroundTransition = transition @@ -405,9 +492,9 @@ public final class PagerComponent: Component { transition: contentBackgroundTransition, component: contentBackground, environment: {}, - containerSize: CGSize(width: availableSize.width, height: availableSize.height - topPanelHeight - contentInsets.bottom + bottomPanelOffset) + containerSize: CGSize(width: availableSize.width, height: availableSize.height - effectiveTopPanelHeight - contentInsets.bottom + bottomPanelOffset) ) - contentBackgroundTransition.setFrame(view: contentBackgroundView, frame: CGRect(origin: CGPoint(x: 0.0, y: topPanelHeight), size: contentBackgroundSize)) + contentBackgroundTransition.setFrame(view: contentBackgroundView, frame: CGRect(origin: CGPoint(x: 0.0, y: effectiveTopPanelHeight), size: contentBackgroundSize)) } else { if let contentBackgroundView = self.contentBackgroundView { self.contentBackgroundView = nil @@ -558,13 +645,44 @@ public final class PagerComponent: Component { return } - if let absoluteOffsetToClosestEdge = update.absoluteOffsetToClosestEdge { - contentView.scrollingPanelOffsetToClosestEdge = absoluteOffsetToClosestEdge - } else { - contentView.scrollingPanelOffsetToClosestEdge = 1000.0 + var offsetDelta: CGFloat? + offsetDelta = (update.absoluteOffsetToTopEdge ?? 0.0) - contentView.scrollingPanelOffsetToTopEdge + + 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) + } } - - state?.updated(transition: update.transition) } } diff --git a/submodules/Display/Source/ContainedViewLayoutTransition.swift b/submodules/Display/Source/ContainedViewLayoutTransition.swift index 6ec8dccddc..15fea6c105 100644 --- a/submodules/Display/Source/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Source/ContainedViewLayoutTransition.swift @@ -146,6 +146,8 @@ 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) @@ -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,6 +283,7 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + node.layer.removeAnimation(forKey: "bounds") node.bounds = bounds if let completion = completion { completion(true) @@ -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,6 +334,7 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: + node.layer.removeAnimation(forKey: "position") node.position = position if let completion = completion { completion(true) @@ -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,6 +625,8 @@ 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) @@ -642,6 +654,8 @@ 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) @@ -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/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/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 4b03fb865c..f92e1ef1f4 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -605,7 +605,7 @@ private func loadItem(path: String) -> AnimationCacheItem? { } let decompressedSize = readUInt32(data: compressedData, offset: 0) - if decompressedSize <= 0 || decompressedSize > 20 * 1024 * 1024 { + if decompressedSize <= 0 || decompressedSize > 40 * 1024 * 1024 { return nil } guard let data = decompressData(data: compressedData, range: 4 ..< compressedData.count, decompressedSize: Int(decompressedSize)) else { diff --git a/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD b/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD index 7813794065..3ae830cb24 100644 --- a/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/BUILD @@ -13,6 +13,7 @@ swift_library( "//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 index 6b2a4df214..3ecfc8b2e8 100644 --- a/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift @@ -2,37 +2,172 @@ import Foundation import UIKit import Display import AsyncDisplayKit +import PagerComponent -private final class ExpansionPanRecognizer: UIPanGestureRecognizer, UIGestureRecognizerDelegate { - private var targetScrollView: UIScrollView? +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) { + 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 { + if scrollView is ListViewScroller || scrollView is GridNodeScrollerView { + return (nil, false) + } + return (scrollView, false) + } + return (nil, true) +} + +private final class ExpansionPanRecognizer: UIGestureRecognizer, UIGestureRecognizerDelegate { + enum LockDirection { + case up + case down + } - override init(target: Any?, action: Selector?) { + 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 func reset() { - self.targetScrollView = nil + override public func reset() { + super.reset() + + self.state = .possible + self.currentTranslation = CGPoint() } - func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { - /*if let scrollView = otherGestureRecognizer.view as? UIScrollView { - if scrollView.bounds.height > 200.0 { - self.targetScrollView = scrollView - scrollView.contentOffset = 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 func touchesMoved(_ touches: Set, with event: UIEvent) { + 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) + if let _ = view.hitTest(point, with: event) as? UIButton { + } else if let scrollView = traceScrollView(view: view, point: point).0 { + let contentOffset = scrollView.contentOffset + let contentInset = scrollView.contentInset + if contentOffset.y.isLessThanOrEqualTo(contentInset.top) { + 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) - if let targetScrollView = self.targetScrollView { - targetScrollView.contentOffset = CGPoint() + 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) + if let scrollView = traceScrollView(view: view, point: point).0 { + let contentOffset = scrollView.contentOffset + let contentInset = scrollView.contentInset + if contentOffset.y <= contentInset.top { + lockDirection = self.requiredLockDirection + } + } + if let lockDirection = lockDirection { + if abs(translation.y) > 2.0 { + switch lockDirection { + case .up: + if translation.y < 0.0 { + self.state = .began + } else { + self.state = .failed + } + case .down: + if translation.y > 0.0 { + self.state = .began + } else { + self.state = .failed + } + } + } + } 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() } } @@ -66,7 +201,7 @@ public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { return } - let delta = -recognizer.translation(in: self.view).y / scrollableDistance + let delta = -recognizer.translation().y / scrollableDistance self.expansionFraction = max(0.0, min(1.0, self.initialExpansionFraction + delta)) self.expansionUpdated?(.immediate) @@ -75,7 +210,7 @@ public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { return } - let velocity = recognizer.velocity(in: self.view) + let velocity = recognizer.velocity() if abs(self.initialExpansionFraction - self.expansionFraction) > 0.25 { if self.initialExpansionFraction < 0.5 { self.expansionFraction = 1.0 @@ -95,6 +230,11 @@ public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { 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 @@ -107,7 +247,13 @@ public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { self.scrollableDistance = scrollableDistance } + public func expand() { + self.expansionFraction = 1.0 + self.expansionRecognizer?.requiredLockDirection = self.expansionFraction == 0.0 ? .up : .down + } + public func collapse() { self.expansionFraction = 0.0 + self.expansionRecognizer?.requiredLockDirection = self.expansionFraction == 0.0 ? .up : .down } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 132efd729c..12a0905961 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -25,14 +25,14 @@ import UndoUI private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) -private final class PremiumBadgeView: BlurredBackgroundView { +private final class PremiumBadgeView: UIView { private let iconLayer: SimpleLayer init() { self.iconLayer = SimpleLayer() self.iconLayer.contents = premiumBadgeIcon?.cgImage - super.init(color: .clear, enableBlur: true) + super.init(frame: CGRect()) self.layer.addSublayer(self.iconLayer) } @@ -42,11 +42,13 @@ private final class PremiumBadgeView: BlurredBackgroundView { } func update(backgroundColor: UIColor, size: CGSize) { - self.updateColor(color: backgroundColor, transition: .immediate) + //self.updateColor(color: backgroundColor, transition: .immediate) + self.backgroundColor = backgroundColor + self.layer.cornerRadius = size.width / 2.0 self.iconLayer.frame = CGRect(origin: CGPoint(), size: size).insetBy(dx: 2.0, dy: 2.0) - super.update(size: size, cornerRadius: min(size.width / 2.0, size.height / 2.0), transition: .immediate) + //super.update(size: size, cornerRadius: min(size.width / 2.0, size.height / 2.0), transition: .immediate) } } @@ -150,6 +152,7 @@ public final class EmojiPagerContentComponent: Component { case detailed } + public let id: AnyHashable public let context: AccountContext public let animationCache: AnimationCache public let animationRenderer: MultiAnimationRenderer @@ -158,6 +161,7 @@ public final class EmojiPagerContentComponent: Component { public let itemLayoutType: ItemLayoutType public init( + id: AnyHashable, context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, @@ -165,6 +169,7 @@ public final class EmojiPagerContentComponent: Component { itemGroups: [ItemGroup], itemLayoutType: ItemLayoutType ) { + self.id = id self.context = context self.animationCache = animationCache self.animationRenderer = animationRenderer @@ -174,6 +179,9 @@ public final class EmojiPagerContentComponent: Component { } public static func ==(lhs: EmojiPagerContentComponent, rhs: EmojiPagerContentComponent) -> Bool { + if lhs.id != rhs.id { + return false + } if lhs.context !== rhs.context { return false } @@ -196,14 +204,24 @@ public final class EmojiPagerContentComponent: Component { return true } - public final class View: UIView, UIScrollViewDelegate { + public final class Tag { + public let id: AnyHashable + + public init(id: AnyHashable) { + self.id = id + } + } + + public final class View: UIView, UIScrollViewDelegate, ComponentTaggedView { private struct ItemGroupDescription: Equatable { + let id: AnyHashable let hasTitle: Bool let itemCount: Int } private struct ItemGroupLayout: Equatable { let frame: CGRect + let id: AnyHashable let itemTopOffset: CGFloat let itemCount: Int } @@ -230,9 +248,9 @@ public final class EmojiPagerContentComponent: Component { self.verticalSpacing = 9.0 minSpacing = 9.0 case .detailed: - self.itemSize = 60.0 - self.verticalSpacing = 9.0 - minSpacing = 9.0 + self.itemSize = 76.0 + self.verticalSpacing = 2.0 + minSpacing = 2.0 } self.verticalGroupSpacing = 18.0 @@ -254,6 +272,7 @@ public final class EmojiPagerContentComponent: Component { let groupContentSize = CGSize(width: width, height: itemTopOffset + CGFloat(numRowsInGroup) * self.itemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) self.itemGroupLayouts.append(ItemGroupLayout( frame: CGRect(origin: CGPoint(x: 0.0, y: verticalGroupOrigin), size: groupContentSize), + id: itemGroup.id, itemTopOffset: itemTopOffset, itemCount: itemGroup.itemCount )) @@ -281,8 +300,8 @@ public final class EmojiPagerContentComponent: Component { ) } - func visibleItems(for rect: CGRect) -> [(groupIndex: Int, groupItems: Range)] { - var result: [(groupIndex: Int, groupItems: Range)] = [] + func visibleItems(for rect: CGRect) -> [(id: AnyHashable, groupIndex: Int, groupItems: Range)] { + var result: [(id: AnyHashable, groupIndex: Int, groupItems: Range)] = [] for groupIndex in 0 ..< self.itemGroupLayouts.count { let group = self.itemGroupLayouts[groupIndex] @@ -300,6 +319,7 @@ public final class EmojiPagerContentComponent: Component { if maxVisibleIndex >= minVisibleIndex { result.append(( + id: group.id, groupIndex: groupIndex, groupItems: minVisibleIndex ..< (maxVisibleIndex + 1) )) @@ -492,15 +512,19 @@ public final class EmojiPagerContentComponent: Component { } } - private let scrollView: UIScrollView + private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { + } + + private let scrollView: ContentScrollView private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:] - private var visibleGroupHeaders: [AnyHashable: ComponentHostView] = [:] + private var visibleGroupHeaders: [AnyHashable: ComponentView] = [:] private var ignoreScrolling: Bool = false private var component: EmojiPagerContentComponent? private var pagerEnvironment: PagerComponentChildEnvironment? private var theme: PresentationTheme? + private var activeItemUpdated: ActionSlot<(AnyHashable, Transition)>? private var itemLayout: ItemLayout? private var currentContextGestureItemKey: ItemLayer.Key? @@ -508,7 +532,7 @@ public final class EmojiPagerContentComponent: Component { private weak var peekController: PeekController? override init(frame: CGRect) { - self.scrollView = UIScrollView() + self.scrollView = ContentScrollView() super.init(frame: frame) @@ -703,6 +727,31 @@ public final class EmojiPagerContentComponent: Component { 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(groupId: AnyHashable) { + guard let itemLayout = self.itemLayout else { + return + } + for group in itemLayout.itemGroupLayouts { + if group.id == groupId { + let wasIgnoringScrollingEvents = self.ignoreScrolling + self.ignoreScrolling = true + self.scrollView.setContentOffset(self.scrollView.contentOffset, animated: false) + self.ignoreScrolling = wasIgnoringScrollingEvents + + self.scrollView.scrollRectToVisible(CGRect(origin: group.frame.origin.offsetBy(dx: 0.0, dy: floor(-itemLayout.verticalGroupSpacing / 2.0)), size: CGSize(width: 1.0, height: self.scrollView.bounds.height)), animated: true) + } + } + } + @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { if case .ended = recognizer.state { if let component = self.component, let (item, itemKey) = self.item(atPoint: recognizer.location(in: self)), let itemLayer = self.visibleItemLayers[itemKey] { @@ -723,7 +772,12 @@ public final class EmojiPagerContentComponent: Component { return nil } - private var previousScrollingOffset: CGFloat? + private struct ScrollingOffsetState: Equatable { + var value: CGFloat + var isDraggingOrDecelerating: Bool + } + + private var previousScrollingOffset: ScrollingOffsetState? public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { if let presentation = scrollView.layer.presentation() { @@ -759,21 +813,22 @@ public final class EmojiPagerContentComponent: Component { } 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 offsetToClosestEdge = min(offsetToTopEdge, offsetToBottomEdge) - let relativeOffset = scrollView.contentOffset.y - previousScrollingOffsetValue + let relativeOffset = scrollView.contentOffset.y - previousScrollingOffsetValue.value self.pagerEnvironment?.onChildScrollingUpdate(PagerComponentChildEnvironment.ContentScrollingUpdate( relativeOffset: relativeOffset, - absoluteOffsetToClosestEdge: offsetToClosestEdge, + absoluteOffsetToTopEdge: offsetToTopEdge, + absoluteOffsetToBottomEdge: offsetToBottomEdge, + isInteracting: isInteracting, transition: transition )) - self.previousScrollingOffset = scrollView.contentOffset.y } - self.previousScrollingOffset = scrollView.contentOffset.y + self.previousScrollingOffset = ScrollingOffsetState(value: scrollView.contentOffset.y, isDraggingOrDecelerating: isInteracting) } private func snappedContentOffset(proposedOffset: CGFloat) -> CGFloat { @@ -808,22 +863,27 @@ public final class EmojiPagerContentComponent: Component { return } + var topVisibleGroupId: AnyHashable? + var validIds = Set() var validGroupHeaderIds = Set() for groupItems in itemLayout.visibleItems(for: self.scrollView.bounds) { + if topVisibleGroupId == nil { + topVisibleGroupId = groupItems.id + } + let itemGroup = component.itemGroups[groupItems.groupIndex] let itemGroupLayout = itemLayout.itemGroupLayouts[groupItems.groupIndex] if let title = itemGroup.title { validGroupHeaderIds.insert(itemGroup.id) - let groupHeaderView: ComponentHostView + let groupHeaderView: ComponentView if let current = self.visibleGroupHeaders[itemGroup.id] { groupHeaderView = current } else { - groupHeaderView = ComponentHostView() + groupHeaderView = ComponentView() self.visibleGroupHeaders[itemGroup.id] = groupHeaderView - self.scrollView.addSubview(groupHeaderView) } let groupHeaderSize = groupHeaderView.update( transition: .immediate, @@ -833,7 +893,12 @@ public final class EmojiPagerContentComponent: Component { environment: {}, containerSize: CGSize(width: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right, height: 100.0) ) - groupHeaderView.frame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) + if let view = groupHeaderView.view { + if view.superview == nil { + self.scrollView.addSubview(view) + } + view.frame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) + } } for index in groupItems.groupItems.lowerBound ..< groupItems.groupItems.upperBound { @@ -848,7 +913,7 @@ public final class EmojiPagerContentComponent: Component { itemLayer = ItemLayer( item: item, context: component.context, - groupId: "keyboard", + groupId: "keyboard-\(Int(itemLayout.itemSize))", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, cache: component.animationCache, @@ -884,17 +949,22 @@ public final class EmojiPagerContentComponent: Component { for (id, groupHeaderView) in self.visibleGroupHeaders { if !validGroupHeaderIds.contains(id) { removedGroupHeaderIds.append(id) - groupHeaderView.removeFromSuperview() + groupHeaderView.view?.removeFromSuperview() } } for id in removedGroupHeaderIds { self.visibleGroupHeaders.removeValue(forKey: id) } + + if let topVisibleGroupId = topVisibleGroupId { + self.activeItemUpdated?.invoke((topVisibleGroupId, .immediate)) + } } func update(component: EmojiPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { self.component = component self.theme = environment[EntityKeyboardChildEnvironment.self].value.theme + self.activeItemUpdated = environment[EntityKeyboardChildEnvironment.self].value.getContentActiveItemUpdated(component.id) let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value self.pagerEnvironment = pagerEnvironment @@ -902,6 +972,7 @@ public final class EmojiPagerContentComponent: Component { var itemGroups: [ItemGroupDescription] = [] for itemGroup in component.itemGroups { itemGroups.append(ItemGroupDescription( + id: itemGroup.id, hasTitle: itemGroup.title != nil, itemCount: itemGroup.items.count )) @@ -918,7 +989,7 @@ public final class EmojiPagerContentComponent: Component { if self.scrollView.scrollIndicatorInsets != pagerEnvironment.containerInsets { self.scrollView.scrollIndicatorInsets = pagerEnvironment.containerInsets } - self.previousScrollingOffset = self.scrollView.contentOffset.y + self.previousScrollingOffset = ScrollingOffsetState(value: scrollView.contentOffset.y, isDraggingOrDecelerating: scrollView.isDragging || scrollView.isDecelerating) self.ignoreScrolling = false self.updateVisibleItems(attemptSynchronousLoads: true) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 5fbe61559c..0e458561ea 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -11,9 +11,14 @@ import BundleIconComponent public final class EntityKeyboardChildEnvironment: Equatable { public let theme: PresentationTheme + public let getContentActiveItemUpdated: (AnyHashable) -> ActionSlot<(AnyHashable, Transition)>? - public init(theme: PresentationTheme) { + public init( + theme: PresentationTheme, + getContentActiveItemUpdated: @escaping (AnyHashable) -> ActionSlot<(AnyHashable, Transition)>? + ) { self.theme = theme + self.getContentActiveItemUpdated = getContentActiveItemUpdated } public static func ==(lhs: EntityKeyboardChildEnvironment, rhs: EntityKeyboardChildEnvironment) -> Bool { @@ -25,7 +30,17 @@ public final class EntityKeyboardChildEnvironment: Equatable { } } +public enum EntitySearchContentType { + case stickers + case gifs +} + public final class EntityKeyboardComponent: Component { + public final class MarkInputCollapsed { + public init() { + } + } + public let theme: PresentationTheme public let bottomInset: CGFloat public let emojiContent: EmojiPagerContentComponent @@ -34,6 +49,9 @@ public final class EntityKeyboardComponent: Component { public let defaultToEmojiTab: Bool public let externalTopPanelContainer: UIView? public let topPanelExtensionUpdated: (CGFloat, Transition) -> Void + public let hideInputUpdated: (Bool, Transition) -> Void + public let makeSearchContainerNode: (EntitySearchContentType) -> EntitySearchContainerNode + public let deviceMetrics: DeviceMetrics public init( theme: PresentationTheme, @@ -43,7 +61,10 @@ public final class EntityKeyboardComponent: Component { gifContent: GifPagerContentComponent, defaultToEmojiTab: Bool, externalTopPanelContainer: UIView?, - topPanelExtensionUpdated: @escaping (CGFloat, Transition) -> Void + topPanelExtensionUpdated: @escaping (CGFloat, Transition) -> Void, + hideInputUpdated: @escaping (Bool, Transition) -> Void, + makeSearchContainerNode: @escaping (EntitySearchContentType) -> EntitySearchContainerNode, + deviceMetrics: DeviceMetrics ) { self.theme = theme self.bottomInset = bottomInset @@ -53,6 +74,9 @@ public final class EntityKeyboardComponent: Component { self.defaultToEmojiTab = defaultToEmojiTab self.externalTopPanelContainer = externalTopPanelContainer self.topPanelExtensionUpdated = topPanelExtensionUpdated + self.hideInputUpdated = hideInputUpdated + self.makeSearchContainerNode = makeSearchContainerNode + self.deviceMetrics = deviceMetrics } public static func ==(lhs: EntityKeyboardComponent, rhs: EntityKeyboardComponent) -> Bool { @@ -77,6 +101,9 @@ public final class EntityKeyboardComponent: Component { if lhs.externalTopPanelContainer != rhs.externalTopPanelContainer { return false } + if lhs.deviceMetrics != rhs.deviceMetrics { + return false + } return true } @@ -85,6 +112,12 @@ public final class EntityKeyboardComponent: Component { 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? override init(frame: CGRect) { self.pagerView = ComponentHostView() @@ -92,6 +125,7 @@ public final class EntityKeyboardComponent: Component { super.init(frame: frame) self.clipsToBounds = true + self.disablesInteractiveTransitionGestureRecognizer = true self.addSubview(self.pagerView) } @@ -101,11 +135,15 @@ public final class EntityKeyboardComponent: Component { } 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 contentTopPanels: [AnyComponentWithIdentity] = [] var contentIcons: [AnyComponentWithIdentity] = [] + var contentAccessoryLeftButtons: [AnyComponentWithIdentity] = [] var contentAccessoryRightButtons: [AnyComponentWithIdentity] = [] + let gifsContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(component.gifContent))) var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] topGifItems.append(EntityKeyboardTopPanelComponent.Item( @@ -126,13 +164,24 @@ public final class EntityKeyboardComponent: Component { )) contentTopPanels.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, - items: topGifItems + items: topGifItems, + activeContentItemIdUpdated: gifsContentItemIdUpdated )))) contentIcons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputGifsIcon", tintColor: component.theme.chat.inputMediaPanel.panelIconColor, maxSize: nil )))) + 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))))) /*contentAccessoryRightButtons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(Button( content: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputSettingsIcon", @@ -152,38 +201,59 @@ public final class EntityKeyboardComponent: Component { ] if let iconName = iconMapping[id] { topStickerItems.append(EntityKeyboardTopPanelComponent.Item( - id: id, - content: AnyComponent(BundleIconComponent( - name: iconName, - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: CGSize(width: 30.0, height: 30.0)) + id: itemGroup.id, + content: AnyComponent(Button( + content: AnyComponent(BundleIconComponent( + name: iconName, + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: CGSize(width: 30.0, height: 30.0) + )), + action: { [weak self] in + self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.id) + } + ).minSize(CGSize(width: 30.0, height: 30.0)) ) )) } } else { if !itemGroup.items.isEmpty { topStickerItems.append(EntityKeyboardTopPanelComponent.Item( - id: AnyHashable(itemGroup.items[0].file.fileId), + id: itemGroup.id, content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( context: component.stickerContent.context, file: itemGroup.items[0].file, animationCache: component.stickerContent.animationCache, - animationRenderer: component.stickerContent.animationRenderer + animationRenderer: component.stickerContent.animationRenderer, + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.id) + } )) )) } } } + let stickersContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() contents.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(component.stickerContent))) contentTopPanels.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, - items: topStickerItems + items: topStickerItems, + activeContentItemIdUpdated: stickersContentItemIdUpdated )))) contentIcons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputStickersIcon", tintColor: component.theme.chat.inputMediaPanel.panelIconColor, maxSize: nil )))) + 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", @@ -195,24 +265,29 @@ public final class EntityKeyboardComponent: Component { } ).minSize(CGSize(width: 38.0, height: 38.0))))) + let emojiContentItemIdUpdated = ActionSlot<(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 { topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( - id: AnyHashable(itemGroup.items[0].file.fileId), + id: itemGroup.id, content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( context: component.emojiContent.context, file: itemGroup.items[0].file, animationCache: component.emojiContent.animationCache, - animationRenderer: component.emojiContent.animationRenderer + animationRenderer: component.emojiContent.animationRenderer, + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.id) + } )) )) } } contentTopPanels.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, - items: topEmojiItems + items: topEmojiItems, + activeContentItemIdUpdated: emojiContentItemIdUpdated )))) contentIcons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputEmojiIcon", @@ -237,6 +312,7 @@ public final class EntityKeyboardComponent: Component { contents: contents, contentTopPanels: contentTopPanels, contentIcons: contentIcons, + contentAccessoryLeftButtons: contentAccessoryLeftButtons, contentAccessoryRightButtons: contentAccessoryRightButtons, defaultId: component.defaultToEmojiTab ? "emoji" : "stickers", contentBackground: AnyComponent(BlurredBackgroundComponent( @@ -253,21 +329,149 @@ public final class EntityKeyboardComponent: Component { self?.component?.emojiContent.inputInteraction.deleteBackwards() } )), - panelStateUpdated: { panelState, transition in - component.topPanelExtensionUpdated(panelState.topPanelHeight, transition) - } + panelStateUpdated: { [weak self] panelState, transition in + guard let strongSelf = self else { + return + } + strongSelf.topPanelExtensionUpdated(height: panelState.topPanelHeight, transition: transition) + }, + hidePanels: self.searchComponent != nil )), environment: { - EntityKeyboardChildEnvironment(theme: component.theme) + EntityKeyboardChildEnvironment( + theme: component.theme, + 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 transition.userData(MarkInputCollapsed.self) != nil { + self.searchComponent = nil + } + + 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.stickerContent.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 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, 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, Transition(animation: .curve(duration: 0.4, curve: .spring))) + } + + private func scrollToItemGroup(contentId: String, groupId: AnyHashable) { + if let pagerView = self.pagerView.findTaggedView(tag: EmojiPagerContentComponent.Tag(id: contentId)) as? EmojiPagerContentComponent.View { + pagerView.scrollToItemGroup(groupId: groupId) + } + } } public func makeView() -> View { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift index 16c2a40147..ff57b95ec9 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift @@ -81,7 +81,7 @@ private final class BottomPanelIconComponent: Component { } final class EntityKeyboardBottomPanelComponent: Component { - typealias EnvironmentType = PagerComponentPanelEnvironment + typealias EnvironmentType = PagerComponentPanelEnvironment let theme: PresentationTheme let bottomInset: CGFloat @@ -111,16 +111,19 @@ final class EntityKeyboardBottomPanelComponent: Component { final class View: UIView { private final class AccessoryButtonView { let id: AnyHashable + var component: AnyComponent let view: ComponentHostView - init(id: AnyHashable, 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] = [:] @@ -160,9 +163,61 @@ final class EntityKeyboardBottomPanelComponent: Component { let intrinsicHeight: CGFloat = 38.0 let height = intrinsicHeight + component.bottomInset - let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value + 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: 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 { @@ -175,11 +230,12 @@ final class EntityKeyboardBottomPanelComponent: Component { if let rightAccessoryButtonComponent = rightAccessoryButtonComponent { var rightAccessoryButtonTransition = transition let rightAccessoryButton: AccessoryButtonView - if let current = self.rightAccessoryButton, current.id == rightAccessoryButtonComponent.id { + 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, view: ComponentHostView()) + rightAccessoryButton = AccessoryButtonView(id: rightAccessoryButtonComponent.id, component: rightAccessoryButtonComponent.component, view: ComponentHostView()) self.rightAccessoryButton = rightAccessoryButton self.addSubview(rightAccessoryButton.view) } @@ -195,7 +251,7 @@ final class EntityKeyboardBottomPanelComponent: Component { self.rightAccessoryButton = nil } - if previousRightAccessoryButton !== self.rightAccessoryButton?.view { + if previousRightAccessoryButton?.view !== self.rightAccessoryButton?.view { if case .none = transition.animation { previousRightAccessoryButton?.view.removeFromSuperview() } else { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift index 875bdd0156..e4a6fe549f 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -7,8 +7,25 @@ import TelegramPresentationData import TelegramCore import Postbox +final class EntityKeyboardTopContainerPanelEnvironment: Equatable { + let visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + + init( + visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + ) { + self.visibilityFractionUpdated = visibilityFractionUpdated + } + + static func ==(lhs: EntityKeyboardTopContainerPanelEnvironment, rhs: EntityKeyboardTopContainerPanelEnvironment) -> Bool { + if lhs.visibilityFractionUpdated !== rhs.visibilityFractionUpdated { + return false + } + return true + } +} + final class EntityKeyboardTopContainerPanelComponent: Component { - typealias EnvironmentType = PagerComponentPanelEnvironment + typealias EnvironmentType = PagerComponentPanelEnvironment let theme: PresentationTheme @@ -26,13 +43,20 @@ final class EntityKeyboardTopContainerPanelComponent: Component { return true } + private final class PanelView { + let view = ComponentHostView() + let visibilityFractionUpdated = ActionSlot<(CGFloat, Transition)>() + } + final class View: UIView { - private var panelViews: [AnyHashable: ComponentHostView] = [:] + private var panelViews: [AnyHashable: PanelView] = [:] private var component: EntityKeyboardTopContainerPanelComponent? - private var panelEnvironment: PagerComponentPanelEnvironment? + private var panelEnvironment: PagerComponentPanelEnvironment? private weak var state: EmptyComponentState? + private var visibilityFraction: CGFloat = 1.0 + override init(frame: CGRect) { super.init(frame: frame) } @@ -84,26 +108,30 @@ final class EntityKeyboardTopContainerPanelComponent: Component { validPanelIds.insert(panel.id) var panelTransition = transition - let panelView: ComponentHostView + let panelView: PanelView if let current = self.panelViews[panel.id] { panelView = current } else { panelTransition = .immediate - panelView = ComponentHostView() + panelView = PanelView() self.panelViews[panel.id] = panelView - self.addSubview(panelView) + self.addSubview(panelView.view) } - let _ = panelView.update( + let _ = panelView.view.update( transition: panelTransition, component: panel.component, - environment: {}, + environment: { + EntityKeyboardTopContainerPanelEnvironment( + visibilityFractionUpdated: panelView.visibilityFractionUpdated + ) + }, containerSize: panelFrame.size ) if isInBounds { - transition.animatePosition(view: panelView, from: CGPoint(x: transitionOffsetFraction * availableSize.width, y: 0.0), to: CGPoint(), additive: true, completion: nil) + transition.animatePosition(view: panelView.view, from: CGPoint(x: transitionOffsetFraction * availableSize.width, y: 0.0), to: CGPoint(), additive: true, completion: nil) } - panelTransition.setFrame(view: panelView, frame: panelFrame, completion: { [weak self] completed in + panelTransition.setFrame(view: panelView.view, frame: panelFrame, completion: { [weak self] completed in if isPartOfTransition && completed { self?.state?.updated(transition: .immediate) } @@ -115,15 +143,34 @@ final class EntityKeyboardTopContainerPanelComponent: Component { for (id, panelView) in self.panelViews { if !validPanelIds.contains(id) { removedPanelIds.append(id) - panelView.removeFromSuperview() + 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) + } + 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)) + } + } } func makeView() -> View { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 69ee408867..1dbf32cdb8 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -17,17 +17,20 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { let file: TelegramMediaFile let animationCache: AnimationCache let animationRenderer: MultiAnimationRenderer + let pressed: () -> Void init( context: AccountContext, file: TelegramMediaFile, animationCache: AnimationCache, - animationRenderer: MultiAnimationRenderer + animationRenderer: MultiAnimationRenderer, + pressed: @escaping () -> Void ) { self.context = context self.file = file self.animationCache = animationCache self.animationRenderer = animationRenderer + self.pressed = pressed } static func ==(lhs: EntityKeyboardAnimationTopPanelComponent, rhs: EntityKeyboardAnimationTopPanelComponent) -> Bool { @@ -49,16 +52,27 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { final class View: UIView { var itemLayer: EmojiPagerContentComponent.View.ItemLayer? + var component: EntityKeyboardAnimationTopPanelComponent? 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 + if self.itemLayer == nil { let itemLayer = EmojiPagerContentComponent.View.ItemLayer( item: EmojiPagerContentComponent.Item( @@ -97,7 +111,7 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { } final class EntityKeyboardTopPanelComponent: Component { - typealias EnvironmentType = Empty + typealias EnvironmentType = EntityKeyboardTopContainerPanelEnvironment final class Item: Equatable { let id: AnyHashable @@ -122,13 +136,16 @@ final class EntityKeyboardTopPanelComponent: Component { let theme: PresentationTheme let items: [Item] + let activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)> init( theme: PresentationTheme, - items: [Item] + items: [Item], + activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)> ) { self.theme = theme self.items = items + self.activeContentItemIdUpdated = activeContentItemIdUpdated } static func ==(lhs: EntityKeyboardTopPanelComponent, rhs: EntityKeyboardTopPanelComponent) -> Bool { @@ -138,6 +155,9 @@ final class EntityKeyboardTopPanelComponent: Component { if lhs.items != rhs.items { return false } + if lhs.activeContentItemIdUpdated !== rhs.activeContentItemIdUpdated { + return false + } return true } @@ -188,6 +208,8 @@ final class EntityKeyboardTopPanelComponent: Component { private var itemLayout: ItemLayout? private var ignoreScrolling: Bool = false + private var visibilityFraction: CGFloat = 1.0 + private var component: EntityKeyboardTopPanelComponent? override init(frame: CGRect) { @@ -296,16 +318,63 @@ final class EntityKeyboardTopPanelComponent: Component { } self.ignoreScrolling = false - if let _ = component.items.first { - self.highlightedIconBackgroundView.isHidden = false - let itemFrame = itemLayout.containerFrame(at: 0) - transition.setFrame(view: self.highlightedIconBackgroundView, frame: itemFrame) - } - self.updateVisibleItems(attemptSynchronousLoads: true) + environment[EntityKeyboardTopContainerPanelEnvironment.self].value.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, transition) in + guard let strongSelf = self else { + return + } + strongSelf.activeContentItemIdUpdated(itemId: itemId, 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, transition: Transition) { + guard let component = self.component, let itemLayout = self.itemLayout else { + return + } + + var found = false + for i in 0 ..< component.items.count { + if component.items[i].id == itemId { + found = true + self.highlightedIconBackgroundView.isHidden = false + let itemFrame = itemLayout.containerFrame(at: i) + transition.setFrame(view: self.highlightedIconBackgroundView, frame: itemFrame) + + break + } + } + if !found { + self.highlightedIconBackgroundView.isHidden = true + } + } } func makeView() -> View { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift new file mode 100644 index 0000000000..a6febf912f --- /dev/null +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift @@ -0,0 +1,118 @@ +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() + self.containerNode = containerNode + self.addSubnode(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 index 3b8a5c5c17..630000f39b 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -453,16 +453,18 @@ public final class GifPagerContentComponent: Component { } private func updateScrollingOffset(transition: Transition) { + let isInteracting = scrollView.isDragging || scrollView.isTracking || 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 offsetToClosestEdge = min(offsetToTopEdge, offsetToBottomEdge) let relativeOffset = scrollView.contentOffset.y - previousScrollingOffsetValue self.pagerEnvironment?.onChildScrollingUpdate(PagerComponentChildEnvironment.ContentScrollingUpdate( relativeOffset: relativeOffset, - absoluteOffsetToClosestEdge: offsetToClosestEdge, + absoluteOffsetToTopEdge: offsetToTopEdge, + absoluteOffsetToBottomEdge: offsetToBottomEdge, + isInteracting: isInteracting, transition: transition )) self.previousScrollingOffset = scrollView.contentOffset.y diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index c952603feb..34a79ff6e8 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -34,18 +34,6 @@ open class MultiAnimationRenderTarget: SimpleLayer { } } -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 diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index f498039eb7..81e19b79b4 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1523,7 +1523,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.chatDisplayNode.setupSendActionOnViewUpdate({ if let strongSelf = self { - strongSelf.chatDisplayNode.inputPanelContainerNode.collapse() + strongSelf.chatDisplayNode.collapseInput() + strongSelf.updateChatPresentationInterfaceState(animated: true, interactive: false, { current in var current = current current = current.updatedInterfaceState { interfaceState in @@ -1614,6 +1615,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) }.updatedInputMode { current in if case let .media(mode, maybeExpanded, focused) = current, maybeExpanded != nil { @@ -9931,7 +9934,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G case .media: break default: - self.chatDisplayNode.inputPanelContainerNode.collapse() + self.chatDisplayNode.collapseInput() } if self.isNodeLoaded { diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 3f67c5b134..86f724661d 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -108,6 +108,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 @@ -539,7 +540,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputPanelContainerNode.addSubnode(self.inputPanelClippingNode) self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundNode) self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundSeparatorNode) - self.inputPanelClippingNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode) + self.inputPanelBackgroundNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode) self.contentContainerNode.addSubnode(self.inputContextPanelContainer) @@ -773,8 +774,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.insertSubnode(navigationModalFrame, aboveSubnode: self.contentContainerNode) } if transition.isAnimated, let animateFromFraction = animateFromFraction, animateFromFraction != 1.0 - self.inputPanelContainerNode.expansionFraction { - navigationModalFrame.updateDismissal(transition: transition, progress: animateFromFraction, additionalProgress: 0.0, completion: {}) + 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 @@ -786,11 +789,14 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 + //strongSelf.inputPanelClippingNode.clipsToBounds = false + let _ = strongSelf + let _ = completed }) } @@ -1014,9 +1020,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { }) var insets: UIEdgeInsets + var inputPanelBottomInsetTerm: CGFloat = 0.0 if inputNodeForState != nil { insets = layout.insets(options: []) - insets.bottom = max(insets.bottom, layout.standardInputHeight) + inputPanelBottomInsetTerm = max(insets.bottom, layout.standardInputHeight) } else { insets = layout.insets(options: [.input]) } @@ -1041,13 +1048,15 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 - insets.bottom, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) + 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) } if let prevInputPanelNode = self.inputPanelNode, inputPanelNode.canHandleTransition(from: prevInputPanelNode) { inputPanelNodeHandlesTransition = true @@ -1057,7 +1066,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } 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) + 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) inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) self.inputPanelNode = inputPanelNode if inputPanelNode.supernode !== self { @@ -1065,7 +1074,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 - insets.bottom - 120.0, isSecondary: false, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) + 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) inputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) } } else { @@ -1076,7 +1085,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) + 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) secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) self.secondaryInputPanelNode = secondaryInputPanelNode if secondaryInputPanelNode.supernode == nil { @@ -1084,7 +1093,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 - insets.bottom, isSecondary: true, transition: transition, interfaceState: self.chatPresentationInterfaceState, metrics: layout.metrics) + 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) secondaryInputPanelSize = CGSize(width: layout.size.width, height: inputPanelHeight) } } else { @@ -1165,6 +1174,9 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputNode.topBackgroundExtensionUpdated = { [weak self] transition in self?.updateInputPanelBackgroundExtension(transition: transition) } + inputNode.hideInputUpdated = { [weak self] transition in + self?.updateInputPanelBackgroundExpansion(transition: transition) + } inputNode.expansionFractionUpdated = { [weak self] transition in self?.updateInputPanelBackgroundExpansion(transition: transition) } @@ -1198,6 +1210,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } + if inputNode.hideInput, 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) @@ -1334,6 +1350,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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)) + if let inputNode = self.inputNode { + if inputNode.hideInput { + inputPanelFrame = inputPanelFrame!.offsetBy(dx: 0.0, dy: -inputPanelFrame!.height) + } + } if self.dismissedAsOverlay { inputPanelFrame!.origin.y = layout.size.height } @@ -1362,6 +1383,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputPanelsHeight = 0.0 } + if let inputNode = self.inputNode { + if inputNode.hideInput { + inputPanelsHeight = 0.0 + } + } + let inputBackgroundInset: CGFloat if cleanInsets.bottom < insets.bottom { inputBackgroundInset = 0.0 @@ -1557,8 +1584,10 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if immediatelyLayoutInputNodeAndAnimateAppearance { inputPanelUpdateTransition = .immediate } + self.inputPanelBackgroundNode.update(size: CGSize(width: intrinsicInputPanelBackgroundNodeSize.width, height: intrinsicInputPanelBackgroundNodeSize.height + inputPanelBackgroundExtension), transition: inputPanelUpdateTransition) - transition.updateFrame(node: self.inputPanelBottomBackgroundSeparatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: self.inputPanelBackgroundNode.frame.maxY + inputPanelBackgroundExtension), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) + 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) @@ -1670,9 +1699,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 @@ -1929,10 +1956,26 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } 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.inputPanelBackgroundNode.frame.maxY + extensionValue), size: CGSize(width: self.inputPanelBackgroundNode.bounds.width, height: UIScreenPixel))) + 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 { + 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) } @@ -2222,6 +2265,18 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.view.window?.endEditing(true) } + func collapseInput() { + if self.inputPanelContainerNode.expansionFraction != 0.0 { + self.inputPanelContainerNode.collapse() + if let inputNode = self.inputNode { + inputNode.hideInput = false + if let inputNode = inputNode as? ChatEntityKeyboardInputNode { + inputNode.markInputCollapsed() + } + } + } + } + private func scheduleLayoutTransitionRequest(_ transition: ContainedViewLayoutTransition) { let requestId = self.scheduledLayoutTransitionRequestId self.scheduledLayoutTransitionRequestId += 1 @@ -2248,7 +2303,13 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } let _ = peerId - let inputNode = ChatEntityKeyboardInputNode(context: self.context, currentInputData: inputMediaNodeData, updatedInputData: self.inputMediaNodeDataPromise.get(), defaultToEmojiTab: !self.chatPresentationInterfaceState.interfaceState.effectiveInputState.inputText.string.isEmpty) + let inputNode = ChatEntityKeyboardInputNode( + context: self.context, + currentInputData: inputMediaNodeData, + updatedInputData: self.inputMediaNodeDataPromise.get(), + defaultToEmojiTab: !self.chatPresentationInterfaceState.interfaceState.effectiveInputState.inputText.string.isEmpty, + controllerInteraction: self.controllerInteraction + ) return inputNode } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index d3e258ebe2..ec3ec5f6db 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -206,6 +206,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } return EmojiPagerContentComponent( + id: "emoji", context: context, animationCache: animationCache, animationRenderer: animationRenderer, @@ -386,6 +387,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } return EmojiPagerContentComponent( + id: "stickers", context: context, animationCache: animationCache, animationRenderer: animationRenderer, @@ -393,7 +395,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in var title: String? if group.id == AnyHashable("saved") { - title = nil + //TODO:localize + title = "Saved".uppercased() } else if group.id == AnyHashable("recent") { //TODO:localize title = "Recently Used".uppercased() @@ -444,18 +447,30 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } + private let context: AccountContext private let entityKeyboardView: ComponentHostView private let defaultToEmojiTab: Bool private var currentInputData: InputData private var inputDataDisposable: Disposable? + private let controllerInteraction: ChatControllerInteraction + + private var inputNodeInteraction: ChatMediaInputNodeInteraction? + + private let trendingGifsPromise = Promise(nil) + + private var isMarkInputCollapsed: Bool = false + 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)? - init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool) { + init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction) { + self.context = context self.currentInputData = currentInputData self.defaultToEmojiTab = defaultToEmojiTab + self.controllerInteraction = controllerInteraction + self.entityKeyboardView = ComponentHostView() super.init() @@ -472,12 +487,48 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { strongSelf.currentInputData = inputData strongSelf.performLayout() }) + + self.inputNodeInteraction = ChatMediaInputNodeInteraction( + navigateToCollectionId: { _ in + }, + navigateBackToStickers: { + }, + setGifMode: { _ in + }, + openSettings: { + }, + openTrending: { _ in + }, + dismissTrendingPacks: { _ in + }, + toggleSearch: { _, _, _ in + }, + openPeerSpecificSettings: { + }, + dismissPeerSpecificSettings: { + }, + clearRecentlyUsedStickers: { + } + ) + + 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 + } + }) } deinit { self.inputDataDisposable?.dispose() } + func markInputCollapsed() { + self.isMarkInputCollapsed = true + } + private func performLayout() { guard let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) = self.currentState else { return @@ -488,10 +539,24 @@ final class ChatEntityKeyboardInputNode: 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) { self.currentState = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) + let wasMarkedInputCollapsed = self.isMarkInputCollapsed + self.isMarkInputCollapsed = false + let expandedHeight = standardInputHeight + self.expansionFraction * (maximumHeight - standardInputHeight) + let context = self.context + let controllerInteraction = self.controllerInteraction + let inputNodeInteraction = self.inputNodeInteraction! + let trendingGifsPromise = self.trendingGifsPromise + + var mappedTransition = Transition(transition) + + if wasMarkedInputCollapsed { + mappedTransition = mappedTransition.withUserData(EntityKeyboardComponent.MarkInputCollapsed()) + } + let entityKeyboardSize = self.entityKeyboardView.update( - transition: Transition(transition), + transition: mappedTransition, component: AnyComponent(EntityKeyboardComponent( theme: interfaceState.theme, bottomInset: bottomInset, @@ -508,7 +573,39 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { strongSelf.topBackgroundExtension = topPanelExtension strongSelf.topBackgroundExtensionUpdated?(transition.containedViewLayoutTransition) } - } + }, + hideInputUpdated: { [weak self] hideInput, transition in + guard let strongSelf = self else { + return + } + if strongSelf.hideInput != hideInput { + strongSelf.hideInput = hideInput + strongSelf.hideInputUpdated?(transition.containedViewLayoutTransition) + } + }, + makeSearchContainerNode: { content in + 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 )), environment: {}, containerSize: CGSize(width: width, height: expandedHeight) diff --git a/submodules/TelegramUI/Sources/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index da22776da3..cf978d6891 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -16,6 +16,9 @@ class ChatInputNode: ASDisplayNode { var topBackgroundExtension: CGFloat = 41.0 var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> Void)? + var hideInput: Bool = false + var hideInputUpdated: ((ContainedViewLayoutTransition) -> Void)? + var expansionFraction: CGFloat = 0.0 var expansionFractionUpdated: ((ContainedViewLayoutTransition) -> Void)? diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index e7ba397f5e..dbccddb807 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -2454,10 +2454,12 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } } else { switch presentationInterfaceState.inputMode { - case .text, .media: + case .text: self.interfaceInteraction?.updateInputModeAndDismissedButtonKeyboardMessageId { _ in return (.none, nil) } + case .media: + break default: break } 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() From 17c61062b84d41b48cf66cd4f9ee1d53adb798d7 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 3 Jul 2022 13:30:00 +0300 Subject: [PATCH 026/113] Update API --- submodules/TelegramApi/Sources/Api0.swift | 7 +- submodules/TelegramApi/Sources/Api10.swift | 14 +-- submodules/TelegramApi/Sources/Api15.swift | 56 ++++++++++++ submodules/TelegramApi/Sources/Api20.swift | 24 +++-- .../ApiUtils/TelegramMediaAction.swift | 4 +- .../SyncCore/SyncCore_CachedUserData.swift | 88 +++++++++++++------ .../SyncCore_TelegramMediaAction.swift | 8 +- .../Peers/UpdateCachedPeerData.swift | 18 +++- .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- 9 files changed, 166 insertions(+), 55 deletions(-) diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 45569922f5..430abca038 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -413,7 +413,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[380460460] = { return Api.MessageAction.parse_messageActionGiftPremium($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) } @@ -578,6 +578,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) } @@ -831,7 +832,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[-1514584156] = { 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) } @@ -1451,6 +1452,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 cd54c48a54..8a78bc01fc 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -1005,7 +1005,7 @@ public extension Api { case messageActionEmpty case messageActionGameScore(gameId: Int64, score: Int32) case messageActionGeoProximityReached(fromId: Api.Peer, toId: Api.Peer, distance: Int32) - case messageActionGiftPremium(currency: String, amount: Int64, duration: 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 @@ -1139,13 +1139,13 @@ public extension Api { toId.serialize(buffer, true) serializeInt32(distance, buffer: buffer, boxed: false) break - case .messageActionGiftPremium(let currency, let amount, let duration): + case .messageActionGiftPremium(let currency, let amount, let months): if boxed { - buffer.appendInt32(380460460) + buffer.appendInt32(-1415514682) } serializeString(currency, buffer: buffer, boxed: false) serializeInt64(amount, buffer: buffer, boxed: false) - serializeInt32(duration, buffer: buffer, boxed: false) + serializeInt32(months, buffer: buffer, boxed: false) break case .messageActionGroupCall(let flags, let call, let duration): if boxed { @@ -1306,8 +1306,8 @@ public extension Api { 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 duration): - return ("messageActionGiftPremium", [("currency", String(describing: currency)), ("amount", String(describing: amount)), ("duration", String(describing: duration))]) + 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): @@ -1532,7 +1532,7 @@ public extension Api { let _c2 = _2 != nil let _c3 = _3 != nil if _c1 && _c2 && _c3 { - return Api.MessageAction.messageActionGiftPremium(currency: _1!, amount: _2!, duration: _3!) + return Api.MessageAction.messageActionGiftPremium(currency: _1!, amount: _2!, months: _3!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api15.swift b/submodules/TelegramApi/Sources/Api15.swift index b09a1ee009..91c4c76183 100644 --- a/submodules/TelegramApi/Sources/Api15.swift +++ b/submodules/TelegramApi/Sources/Api15.swift @@ -500,6 +500,62 @@ public extension Api { } } +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 diff --git a/submodules/TelegramApi/Sources/Api20.swift b/submodules/TelegramApi/Sources/Api20.swift index c32090fe33..737828ce5d 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -566,13 +566,13 @@ public extension Api { } 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?, giftPremiumUrl: String?) + 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 .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 giftPremiumUrl): + 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(-1514584156) + buffer.appendInt32(-994968513) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt64(id, buffer: buffer, boxed: false) @@ -589,15 +589,19 @@ public extension Api { 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 {serializeString(giftPremiumUrl!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 19) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(premiumGifts!.count)) + for item in premiumGifts! { + item.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, let giftPremiumUrl): - 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)), ("giftPremiumUrl", String(describing: giftPremiumUrl))]) + 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))]) } } @@ -644,8 +648,10 @@ public extension Api { if Int(_1!) & Int(1 << 18) != 0 {if let signature = reader.readInt32() { _15 = Api.parse(reader, signature: signature) as? Api.ChatAdminRights } } - var _16: String? - if Int(_1!) & Int(1 << 19) != 0 {_16 = parseString(reader) } + 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 @@ -663,7 +669,7 @@ public extension Api { 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, giftPremiumUrl: _16) + 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 diff --git a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift index 3c4b065802..19a12ad360 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaAction.swift @@ -85,8 +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, duration): - return TelegramMediaAction(action: .giftPremium(currency: currency, amount: amount, duration: duration)) + case let .messageActionGiftPremium(currency, amount, months): + return TelegramMediaAction(action: .giftPremium(currency: currency, amount: amount, months: months)) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index 865420f7cf..f3c71f42c1 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,7 +100,7 @@ public final class CachedUserData: CachedPeerData { public let autoremoveTimeout: CachedPeerAutoremoveTimeout public let themeEmoticon: String? public let photo: TelegramMediaImage? - public let giftPremiumUrl: String? + public let premiumGiftOptions: [CachedPremiumGiftOption] public let peerIds: Set public let messageIds: Set @@ -85,12 +121,12 @@ public final class CachedUserData: CachedPeerData { self.autoremoveTimeout = .unknown self.themeEmoticon = nil self.photo = nil - self.giftPremiumUrl = nil + self.premiumGiftOptions = [] 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?, giftPremiumUrl: String?) { + 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]) { self.about = about self.botInfo = botInfo self.peerStatusSettings = peerStatusSettings @@ -105,7 +141,7 @@ public final class CachedUserData: CachedPeerData { self.autoremoveTimeout = autoremoveTimeout self.themeEmoticon = themeEmoticon self.photo = photo - self.giftPremiumUrl = giftPremiumUrl + self.premiumGiftOptions = premiumGiftOptions self.peerIds = Set() @@ -146,8 +182,8 @@ public final class CachedUserData: CachedPeerData { } else { self.photo = nil } - - self.giftPremiumUrl = decoder.decodeOptionalStringForKey("gpu") + + self.premiumGiftOptions = decoder.decodeObjectArrayWithDecoderForKey("pgo") as [CachedPremiumGiftOption] self.peerIds = Set() @@ -203,11 +239,7 @@ public final class CachedUserData: CachedPeerData { encoder.encodeNil(forKey: "ph") } - if let giftPremiumUrl = self.giftPremiumUrl, !giftPremiumUrl.isEmpty { - encoder.encodeString(giftPremiumUrl, forKey: "gpu") - } else { - encoder.encodeNil(forKey: "gpu") - } + encoder.encodeObjectArray(self.premiumGiftOptions, forKey: "pgo") } public func isEqual(to: CachedPeerData) -> Bool { @@ -222,66 +254,66 @@ 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 } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } 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, giftPremiumUrl: self.giftPremiumUrl) + 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) } - public func withUpdatedGiftPremiumUrl(_ giftPremiumUrl: 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: self.themeEmoticon, photo: self.photo, giftPremiumUrl: giftPremiumUrl) + 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) } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift index b1a1d376b3..66606f6fb3 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaAction.swift @@ -51,7 +51,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { case setChatTheme(emoji: String) case joinedByRequest case webViewData(String) - case giftPremium(currency: String, amount: Int64, duration: Int32) + case giftPremium(currency: String, amount: Int64, months: Int32) public init(decoder: PostboxDecoder) { let rawValue: Int32 = decoder.decodeInt32ForKey("_rawValue", orElse: 0) @@ -121,7 +121,7 @@ public enum TelegramMediaActionType: PostboxCoding, Equatable { case 26: self = .webViewData(decoder.decodeStringForKey("t", orElse: "")) case 27: - self = .giftPremium(currency: decoder.decodeStringForKey("currency", orElse: ""), amount: decoder.decodeInt64ForKey("amount", orElse: 0), duration: decoder.decodeInt32ForKey("duration", orElse: 0)) + self = .giftPremium(currency: decoder.decodeStringForKey("currency", orElse: ""), amount: decoder.decodeInt64ForKey("amount", orElse: 0), months: decoder.decodeInt32ForKey("months", orElse: 0)) default: self = .unknown } @@ -246,11 +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, duration): + case let .giftPremium(currency, amount, months): encoder.encodeInt32(27, forKey: "_rawValue") encoder.encodeString(currency, forKey: "currency") encoder.encodeInt64(amount, forKey: "amount") - encoder.encodeInt32(duration, forKey: "duration") + encoder.encodeInt32(months, forKey: "months") } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 7aa4e71284..a8f0eb91ea 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -234,7 +234,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee previous = CachedUserData() } switch fullUser { - case let .userFull(userFullFlags, _, userFullAbout, userFullSettings, profilePhoto, _, userFullBotInfo, userFullPinnedMsgId, userFullCommonChatsCount, _, userFullTtlPeriod, userFullThemeEmoticon, _, _, _, giftPremiumUrl): + 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 @@ -252,11 +252,25 @@ 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) - .withUpdatedGiftPremiumUrl(giftPremiumUrl) + .withUpdatedPremiumGiftOptions(premiumGiftOptions) } }) } diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 6672db95ca..e29d553d77 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -4059,7 +4059,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }))) } - if !user.isDeleted && user.botInfo == nil && !user.flags.contains(.isSupport), let cachedData = data.cachedData as? CachedUserData, let _ = cachedData.giftPremiumUrl { + 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 From 59ab7bce00207761fdea581a2ea1f3a8ad0362f2 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 3 Jul 2022 13:30:48 +0300 Subject: [PATCH 027/113] Tune account deletion layout --- .../Sources/InviteLinkHeaderItem.swift | 11 +++++++++-- .../Sources/DeleteAccountDataController.swift | 15 +++++++++------ .../Sources/DeleteAccountFooterItem.swift | 13 +++++++++++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift index 2eb83c529a..3568985df7 100644 --- a/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift +++ b/submodules/InviteLinksUI/Sources/InviteLinkHeaderItem.swift @@ -18,15 +18,17 @@ public class InviteLinkHeaderItem: ListViewItem, ItemListItem { public let title: String? public let text: String public let animationName: String + public let hideOnSmallScreens: Bool public let sectionId: ItemListSectionId public let linkAction: ((ItemListTextItemLinkAction) -> Void)? - public init(context: AccountContext, theme: PresentationTheme, title: String? = nil, text: String, animationName: String, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) { + public init(context: AccountContext, theme: PresentationTheme, title: String? = nil, text: String, animationName: String, hideOnSmallScreens: Bool = false, sectionId: ItemListSectionId, linkAction: ((ItemListTextItemLinkAction) -> Void)? = nil) { self.context = context self.theme = theme self.title = title self.text = text self.animationName = animationName + self.hideOnSmallScreens = hideOnSmallScreens self.sectionId = sectionId self.linkAction = linkAction } @@ -118,7 +120,11 @@ class InviteLinkHeaderItemNode: ListViewItemNode { if params.width > params.availableHeight && params.width > 320.0 { iconSize = CGSize(width: 140.0, height: 140.0) } else { - iconSize = CGSize(width: 124.0, height: 124.0) + if item.hideOnSmallScreens { + iconSize = .zero + } else { + iconSize = CGSize(width: 124.0, height: 124.0) + } } let topInset: CGFloat = iconSize.height - 4.0 let spacing: CGFloat = 5.0 @@ -137,6 +143,7 @@ class InviteLinkHeaderItemNode: ListViewItemNode { if let _ = item.title { contentSize.height += titleLayout.size.height + spacing } + let insets = itemListNeighborsGroupedInsets(neighbors, params) let layout = ListViewItemNodeLayout(contentSize: contentSize, insets: insets) diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index 2af68895fd..e3997d6095 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -44,7 +44,7 @@ private enum DeleteAccountEntryTag: Equatable, ItemListItemTag { private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { - case header(PresentationTheme, String, String, String) + case header(PresentationTheme, String, String, String, Bool) case peers(PresentationTheme, [EnginePeer]) case phone(PresentationTheme, PresentationStrings) case password(PresentationTheme, String) @@ -76,8 +76,8 @@ private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { static func == (lhs: DeleteAccountDataEntry, rhs: DeleteAccountDataEntry) -> Bool { switch lhs { - case let .header(lhsTheme, lhsAnimation, lhsTitle, lhsText): - if case let .header(rhsTheme, rhsAnimation, rhsTitle, rhsText) = rhs, lhsTheme === rhsTheme, lhsAnimation == rhsAnimation, lhsTitle == rhsTitle, lhsText == rhsText { + case let .header(lhsTheme, lhsAnimation, lhsTitle, lhsText, lhsHideOnSmallScreens): + if case let .header(rhsTheme, rhsAnimation, rhsTitle, rhsText, rhsHideOnSmallScreens) = rhs, lhsTheme === rhsTheme, lhsAnimation == rhsAnimation, lhsTitle == rhsTitle, lhsText == rhsText, lhsHideOnSmallScreens == rhsHideOnSmallScreens { return true } else { return false @@ -117,8 +117,8 @@ private enum DeleteAccountDataEntry: ItemListNodeEntry, Equatable { func item(presentationData: ItemListPresentationData, arguments: Any) -> ListViewItem { let arguments = arguments as! DeleteAccountDataArguments switch self { - case let .header(theme, animation, title, text): - return InviteLinkHeaderItem(context: arguments.context, theme: theme, title: title, text: text, animationName: animation, sectionId: self.section, linkAction: nil) + case let .header(theme, animation, title, text, hideOnSmallScreens): + return InviteLinkHeaderItem(context: arguments.context, theme: theme, title: title, text: text, animationName: animation, hideOnSmallScreens: hideOnSmallScreens, sectionId: self.section, linkAction: nil) case let .peers(_, peers): return DeleteAccountPeersItem(context: arguments.context, theme: presentationData.theme, strings: presentationData.strings, peers: peers, sectionId: self.section) case let .info(_, text): @@ -145,6 +145,7 @@ private func deleteAccountDataEntries(presentationData: PresentationData, mode: let headerTitle: String let headerText: String let headerAnimation: String + var hideOnSmallScreen = false switch mode { case .peers: @@ -163,13 +164,15 @@ private func deleteAccountDataEntries(presentationData: PresentationData, mode: headerAnimation = "Delete4" headerTitle = presentationData.strings.DeleteAccount_EnterPhoneNumber headerText = "" + hideOnSmallScreen = true case .password: headerAnimation = "Delete5" headerTitle = presentationData.strings.DeleteAccount_EnterPassword headerText = "" + hideOnSmallScreen = true } - entries.append(.header(presentationData.theme, headerAnimation, headerTitle, headerText)) + entries.append(.header(presentationData.theme, headerAnimation, headerTitle, headerText, hideOnSmallScreen)) switch mode { case .peers: diff --git a/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift b/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift index b5b9f04b34..3d2cd1966d 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountFooterItem.swift @@ -118,8 +118,17 @@ final class DeleteAccountFooterItemNode: ItemListControllerFooterItemNode { let buttonWidth = layout.size.width - layout.safeInsets.left - layout.safeInsets.right - buttonInset * 2.0 let buttonHeight = self.buttonNode.updateLayout(width: buttonWidth, transition: transition) let topInset: CGFloat = 9.0 - let bottomInset: CGFloat = 23.0 - let spacing: CGFloat = 23.0 + + let bottomInset: CGFloat + let spacing: CGFloat + + if layout.size.width > 320.0 { + bottomInset = 23.0 + spacing = 23.0 + } else { + bottomInset = 16.0 + spacing = 16.0 + } let insets = layout.insets(options: [.input]) From 6691963495e0fcda471b4f46738457321322324d Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 4 Jul 2022 13:51:41 +0200 Subject: [PATCH 028/113] Treat Namespaces.Message.ScheduledLocal as Namespaces.Message.Local --- .../TelegramEngine/Messages/DeleteMessagesInteractively.swift | 2 +- .../Sources/ChatMessageAnimatedStickerItemNode.swift | 4 ++-- .../TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift | 2 +- .../Sources/ChatMessageInteractiveInstantVideoNode.swift | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessagesInteractively.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessagesInteractively.swift index 3531dc0ba5..29d426d335 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessagesInteractively.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/DeleteMessagesInteractively.swift @@ -53,7 +53,7 @@ func deleteMessagesInteractively(transaction: Transaction, stateManager: Account if peerId.namespace == Namespaces.Peer.CloudChannel || peerId.namespace == Namespaces.Peer.CloudGroup || peerId.namespace == Namespaces.Peer.CloudUser { let remoteMessageIds = peerMessageIds.filter { id in - if id.namespace == Namespaces.Message.Local { + if id.namespace == Namespaces.Message.Local || id.namespace == Namespaces.Message.ScheduledLocal { return false } return true diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index c11adf3f34..4bc9f720fa 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -474,10 +474,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView { override func setupItem(_ item: ChatMessageItem, synchronousLoad: Bool) { super.setupItem(item, synchronousLoad: synchronousLoad) - if item.message.id.namespace == Namespaces.Message.Local { + if item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal { self.wasPending = true } - if self.wasPending && item.message.id.namespace != Namespaces.Message.Local { + if self.wasPending && (item.message.id.namespace != Namespaces.Message.Local && item.message.id.namespace != Namespaces.Message.ScheduledLocal) { self.didChangeFromPendingToSent = true } diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index 4291fba002..6fc9c5eddb 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -81,7 +81,7 @@ class ChatMessageInstantVideoItemNode: ChatMessageItemView, UIGestureRecognizerD self.interactiveVideoNode.shouldOpen = { [weak self] in if let strongSelf = self { - if let item = strongSelf.item, item.message.id.namespace == Namespaces.Message.Local { + if let item = strongSelf.item, (item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal) { return false } return !strongSelf.animatingHeight diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift index 57a9143653..2e50baecd8 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveInstantVideoNode.swift @@ -231,7 +231,7 @@ class ChatMessageInteractiveInstantVideoNode: ASDisplayNode { break } } - if item.message.id.namespace == Namespaces.Message.Local { + if item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal { notConsumed = true } From ed2585a3378f488c00de23cd8f9904a4fcdc1b4b Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 4 Jul 2022 15:49:09 +0300 Subject: [PATCH 029/113] Account deletion fixes --- .../Sources/DeleteAccountDataController.swift | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift index e3997d6095..ce7a7166b5 100644 --- a/submodules/SettingsUI/Sources/DeleteAccountDataController.swift +++ b/submodules/SettingsUI/Sources/DeleteAccountDataController.swift @@ -462,12 +462,13 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat return updated } + secondaryActionDisabled = false presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])) }, completed: { dismissImpl?() let presentGlobalController = context.sharedContext.presentGlobalController - let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: true).start(completed: { + let _ = logoutFromAccount(id: accountId, accountManager: accountManager, alreadyLoggedOutRemotely: false).start(completed: { Queue.mainQueue().after(0.1) { presentGlobalController(UndoOverlayController(presentationData: presentationData, content: .info(title: nil, text: presentationData.strings.DeleteAccount_Success), elevatedLayout: true, animateInAsReplacement: false, action: { _ in return false }), nil) } @@ -492,7 +493,11 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat var phoneNumber: String? controller?.forEachItemNode { itemNode in if let itemNode = itemNode as? DeleteAccountPhoneItemNode { - phoneNumber = itemNode.phoneNumber + var phoneValue = itemNode.phoneNumber + if phoneValue.hasPrefix("+939998") { + phoneValue = phoneValue.replacingOccurrences(of: "+939998", with: "+9998") + } + phoneNumber = phoneValue } } @@ -505,6 +510,7 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat phone = "+\(phone)" } if phone != phoneNumber { + secondaryActionDisabled = false presentControllerImpl?(textAlertController(context: context, title: nil, text: presentationData.strings.DeleteAccount_InvalidPhoneNumberError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})])) return } @@ -523,6 +529,8 @@ func deleteAccountDataController(context: AccountContext, mode: DeleteAccountDat let _ = (context.engine.auth.requestTwoStepVerifiationSettings(password: state.password) |> deliverOnMainQueue).start(error: { error in + secondaryActionDisabled = false + updateState { current in var updated = current updated.isLoading = false From c69c578e1d0786a3ce716ec11e19e752080ffb4e Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 5 Jul 2022 17:20:56 +0200 Subject: [PATCH 030/113] Fix typing statuses --- submodules/ChatListUI/Sources/Node/ChatListNode.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/submodules/ChatListUI/Sources/Node/ChatListNode.swift b/submodules/ChatListUI/Sources/Node/ChatListNode.swift index 515dbd6d2b..ef7a2a5ecc 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListNode.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListNode.swift @@ -1312,6 +1312,8 @@ public final class ChatListNode: ListView { switch activity { case .interactingWithEmoji: return true + case .speakingInGroupCall: + return true default: return false } @@ -1343,9 +1345,9 @@ public final class ChatListNode: ListView { return engine.data.get(EngineDataMap( activitiesByPeerId.keys.filter { key in if case .global = key.category { - return false - } else { return true + } else { + return false } }.map { key in return TelegramEngine.EngineData.Item.Peer.Peer(id: key.peerId) From e99cefa2d695d00acf23f42dd05794a09f97bea6 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 5 Jul 2022 19:16:06 +0200 Subject: [PATCH 031/113] Ongoing work on the updated entity input --- .../AttachmentTextInputPanelNode.swift | 8 +- .../Sources/AttachmentPanel.swift | 2 +- .../Sources/ChatTextInputPanelState.swift | 31 +- .../Source/Base/Transition.swift | 79 +++- .../Source/Components/Button.swift | 79 +++- .../Source/Host/ComponentHostView.swift | 15 +- .../Sources/LottieAnimationComponent.swift | 3 - .../Sources/PagerComponent.swift | 110 ++++- .../Display/Source/ContextGesture.swift | 2 +- submodules/Display/Source/PortalView.swift | 2 + submodules/Display/Source/TextNode.swift | 4 + .../Pasteboard/Sources/Pasteboard.swift | 3 + .../ShimmerEffect/Sources/ShimmerEffect.swift | 66 +++ .../Sources/StickerShimmerEffectNode.swift | 4 +- submodules/TelegramUI/BUILD | 2 + .../Sources/ChatInputPanelContainer.swift | 70 ++- .../Components/EntityKeyboard/BUILD | 1 + .../Sources/EmojiPagerContentComponent.swift | 375 ++++++++++++--- .../Sources/EntityKeyboard.swift | 114 ++++- ...tyKeyboardTopContainerPanelComponent.swift | 69 ++- .../EntityKeyboardTopPanelComponent.swift | 434 ++++++++++++++++-- .../Sources/GifPagerContentComponent.swift | 1 + .../Sources/MultiAnimationRenderer.swift | 24 + .../Contents.json | 12 + .../EntityInputGlobeIcon.imageset/planet.pdf | 255 ++++++++++ .../Animations/anim_smiletosticker.json | 1 + .../Animations/anim_stickertosmile.json | 1 + .../Sources/ChatBotStartInputPanelNode.swift | 2 +- .../Sources/ChatButtonKeyboardInputNode.swift | 2 +- .../ChatChannelSubscriberInputPanelNode.swift | 2 +- .../Sources/ChatControllerNode.swift | 47 +- .../Sources/ChatEntityKeyboardInputNode.swift | 54 ++- .../ChatFeedNavigationInputPanelNode.swift | 2 +- .../TelegramUI/Sources/ChatInputNode.swift | 7 +- .../Sources/ChatInputPanelNode.swift | 2 +- .../Sources/ChatInterfaceInputContexts.swift | 5 +- .../Sources/ChatMediaInputNode.swift | 36 +- .../ChatMessageReportInputPanelNode.swift | 2 +- .../ChatMessageSelectionInputPanelNode.swift | 14 +- .../ChatMessageTextBubbleContentNode.swift | 3 +- .../ChatRecordingPreviewInputPanelNode.swift | 2 +- .../ChatRestrictedInputPanelNode.swift | 2 +- .../Sources/ChatSearchInputPanelNode.swift | 10 +- .../ChatTextInputActionButtonsNode.swift | 7 +- .../Sources/ChatTextInputPanelNode.swift | 166 ++++--- .../Sources/ChatUnblockInputPanelNode.swift | 2 +- .../Sources/DeleteChatInputPanelNode.swift | 2 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- .../Sources/PeerSelectionControllerNode.swift | 2 +- ...retChatHandshakeStatusInputPanelNode.swift | 2 +- .../Sources/StringWithAppliedEntities.swift | 2 + 51 files changed, 1827 insertions(+), 317 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/planet.pdf create mode 100644 submodules/TelegramUI/Resources/Animations/anim_smiletosticker.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_stickertosmile.json diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index c0afa5705a..55d5d295a4 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -352,7 +352,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?) { @@ -496,7 +496,7 @@ 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 { + 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) @@ -1110,7 +1110,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 +1121,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/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 0cb84a5b20..547c91d193 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -1098,7 +1098,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/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift index 2e50a789fa..f973517907 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift @@ -3,13 +3,42 @@ import AccountContext import SwiftSignalKit public enum ChatTextInputAccessoryItem: Equatable { + public enum Key: Hashable { + case keyboard + case stickers + case inputButtons + case commands + case silentPost + case messageAutoremoveTimeout + case scheduledMessages + } + case keyboard - case stickers(Bool) + case stickers(isEnabled: Bool, isEmoji: Bool) case inputButtons case commands case silentPost(Bool) case messageAutoremoveTimeout(Int32?) case scheduledMessages + + public var key: Key { + switch self { + case .keyboard: + return .keyboard + case .stickers: + return .stickers + case .inputButtons: + return .inputButtons + case .commands: + return .commands + case .silentPost: + return .silentPost + case .messageAutoremoveTimeout: + return .messageAutoremoveTimeout + case .scheduledMessages: + return .scheduledMessages + } + } } public final class InstantVideoControllerRecordingStatus { diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index ecfc9ec761..a44933d09d 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -128,6 +128,16 @@ private extension Transition.Animation.Curve { } } +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 { @@ -245,6 +255,61 @@ public struct Transition { } } + 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 = layer.presentation()?.bounds ?? 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 = layer.presentation()?.position ?? 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) @@ -356,11 +421,19 @@ 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 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", @@ -374,12 +447,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", diff --git a/submodules/ComponentFlow/Source/Components/Button.swift b/submodules/ComponentFlow/Source/Components/Button.swift index 078558a048..27f749aa5f 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: 1.0, 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.2, 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/Host/ComponentHostView.swift b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift index bd29143893..0e27198b92 100644 --- a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift +++ b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift @@ -106,8 +106,21 @@ public final class ComponentHostView: 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) - return result + if result != self { + return result + } else { + return nil + } } public func findTaggedView(tag: Any) -> UIView? { diff --git a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift index c3887fa3ac..cad54a967a 100644 --- a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift +++ b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift @@ -157,9 +157,6 @@ public final class LottieAnimationComponent: Component { 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"))*/ } self.animationView = view diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index 040f784ca4..a122249858 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -9,11 +9,15 @@ public protocol PagerExpandableScrollView: UIScrollView { public protocol PagerPanGestureRecognizer: UIGestureRecognizer { } +open class PagerExternalTopPanelContainer: SparseContainerView { +} + 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 @@ -21,12 +25,14 @@ public final class PagerComponentChildEnvironment: Equatable { 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 } @@ -61,6 +67,7 @@ public final class PagerComponentPanelEnvironment: Equatabl public let activeContentId: AnyHashable? public let navigateToContentId: (AnyHashable) -> Void public let visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + public let isExpandedUpdated: (Bool, Transition) -> Void init( contentOffset: CGFloat, @@ -70,7 +77,8 @@ public final class PagerComponentPanelEnvironment: Equatabl contentAccessoryRightButtons: [AnyComponentWithIdentity], activeContentId: AnyHashable?, navigateToContentId: @escaping (AnyHashable) -> Void, - visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)>, + isExpandedUpdated: @escaping (Bool, Transition) -> Void ) { self.contentOffset = contentOffset self.contentTopPanels = contentTopPanels @@ -80,6 +88,7 @@ public final class PagerComponentPanelEnvironment: Equatabl self.activeContentId = activeContentId self.navigateToContentId = navigateToContentId self.visibilityFractionUpdated = visibilityFractionUpdated + self.isExpandedUpdated = isExpandedUpdated } public static func ==(lhs: PagerComponentPanelEnvironment, rhs: PagerComponentPanelEnvironment) -> Bool { @@ -122,6 +131,12 @@ public final class PagerComponentViewTag { } } +public enum PagerComponentPanelHideBehavior { + case hideOnScroll + case show + case hide +} + public final class PagerComponent: Component { public typealias EnvironmentType = ChildEnvironmentType @@ -134,10 +149,11 @@ public final class PagerComponent? public let topPanel: AnyComponent>? - public let externalTopPanelContainer: UIView? + public let externalTopPanelContainer: PagerExternalTopPanelContainer? public let bottomPanel: AnyComponent>? public let panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)? - public let hidePanels: Bool + public let isTopPanelExpandedUpdated: (Bool, Transition) -> Void + public let panelHideBehavior: PagerComponentPanelHideBehavior public init( contentInsets: UIEdgeInsets, @@ -149,10 +165,11 @@ public final class PagerComponent?, topPanel: AnyComponent>?, - externalTopPanelContainer: UIView?, + externalTopPanelContainer: PagerExternalTopPanelContainer?, bottomPanel: AnyComponent>?, panelStateUpdated: ((PagerComponentPanelState, Transition) -> Void)?, - hidePanels: Bool + isTopPanelExpandedUpdated: @escaping (Bool, Transition) -> Void, + panelHideBehavior: PagerComponentPanelHideBehavior ) { self.contentInsets = contentInsets self.contents = contents @@ -166,7 +183,8 @@ public final class PagerComponent Bool { @@ -197,7 +215,7 @@ public final class 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 @@ -345,7 +372,9 @@ public final class PagerComponent> - var topPanelTransition = transition + var topPanelTransition = panelStateTransition if let current = self.topPanelView { topPanelView = current } else { topPanelTransition = .immediate topPanelView = ComponentHostView>() - topPanelView.clipsToBounds = true self.topPanelView = topPanelView } @@ -381,7 +409,13 @@ public final class PagerComponent> - var bottomPanelTransition = transition + var bottomPanelTransition = panelStateTransition if let current = self.bottomPanelView { bottomPanelView = current } else { @@ -449,7 +488,9 @@ public final class PagerComponent - var contentBackgroundTransition = transition + var contentBackgroundTransition = panelStateTransition if let current = self.contentBackgroundView { contentBackgroundView = current } else { @@ -633,7 +680,7 @@ public final class PagerComponent View { diff --git a/submodules/Display/Source/ContextGesture.swift b/submodules/Display/Source/ContextGesture.swift index 7a2a1b0de0..217df908aa 100644 --- a/submodules/Display/Source/ContextGesture.swift +++ b/submodules/Display/Source/ContextGesture.swift @@ -36,7 +36,7 @@ public func cancelParentGestures(view: UIView, ignore: [UIGestureRecognizer] = [ node.highligthedChanged(false) } if let superview = view.superview { - cancelParentGestures(view: superview) + cancelParentGestures(view: superview, ignore: ignore) } } 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..9bc8efeef9 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -1435,6 +1435,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)) } } diff --git a/submodules/Pasteboard/Sources/Pasteboard.swift b/submodules/Pasteboard/Sources/Pasteboard.swift index 203d275a49..855805a504 100644 --- a/submodules/Pasteboard/Sources/Pasteboard.swift +++ b/submodules/Pasteboard/Sources/Pasteboard.swift @@ -51,6 +51,9 @@ 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 } 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/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index c0eb480146..7fe179a22d 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -291,6 +291,8 @@ swift_library( "//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/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift index 3ecfc8b2e8..609dee148f 100644 --- a/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift @@ -7,21 +7,18 @@ 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) { + 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{ + } else if !shouldContinue { return (nil, false) } } } if let scrollView = view as? UIScrollView { - if scrollView is ListViewScroller || scrollView is GridNodeScrollerView { - return (nil, false) - } return (scrollView, false) } return (nil, true) @@ -31,6 +28,7 @@ private final class ExpansionPanRecognizer: UIGestureRecognizer, UIGestureRecogn enum LockDirection { case up case down + case any } var requiredLockDirection: LockDirection = .up @@ -83,14 +81,23 @@ private final class ExpansionPanRecognizer: UIGestureRecognizer, UIGestureRecogn var found = false let point = touch.location(in: self.view) - if let _ = view.hitTest(point, with: event) as? UIButton { - } else if let scrollView = traceScrollView(view: view, point: point).0 { - let contentOffset = scrollView.contentOffset - let contentInset = scrollView.contentInset - if contentOffset.y.isLessThanOrEqualTo(contentInset.top) { + + 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 { + if scrollView is ListViewScroller || scrollView is GridNodeScrollerView { + found = false + } else { + found = true + } + } else { found = true } } + if found { self.beginPosition = point } else { @@ -118,28 +125,46 @@ private final class ExpansionPanRecognizer: UIGestureRecognizer, UIGestureRecogn } 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 { - let contentOffset = scrollView.contentOffset - let contentInset = scrollView.contentInset - if contentOffset.y <= contentInset.top { - lockDirection = self.requiredLockDirection + 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 { @@ -179,6 +204,7 @@ public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { 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() @@ -231,6 +257,8 @@ public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { } } + self.stableIsExpanded = self.expansionFraction == 1.0 + if let expansionRecognizer = self.expansionRecognizer { expansionRecognizer.requiredLockDirection = self.expansionFraction == 0.0 ? .up : .down } @@ -250,10 +278,24 @@ public final class ChatInputPanelContainer: SparseNode, UIScrollViewDelegate { 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/EntityKeyboard/BUILD b/submodules/TelegramUI/Components/EntityKeyboard/BUILD index 2c3681c3ec..353a3fa407 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/BUILD +++ b/submodules/TelegramUI/Components/EntityKeyboard/BUILD @@ -38,6 +38,7 @@ swift_library( "//submodules/PremiumUI:PremiumUI", "//submodules/StickerPackPreviewUI:StickerPackPreviewUI", "//submodules/UndoUI:UndoUI", + "//submodules/Components/MultilineTextComponent:MultilineTextComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 12a0905961..37500a96b5 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -230,7 +230,8 @@ public final class EmojiPagerContentComponent: Component { var width: CGFloat var containerInsets: UIEdgeInsets var itemGroupLayouts: [ItemGroupLayout] - var itemSize: CGFloat + var nativeItemSize: CGFloat + let visibleItemSize: CGFloat var horizontalSpacing: CGFloat var verticalSpacing: CGFloat var verticalGroupSpacing: CGFloat @@ -241,14 +242,17 @@ public final class EmojiPagerContentComponent: Component { self.width = width self.containerInsets = containerInsets + let minItemsPerRow: Int let minSpacing: CGFloat switch itemLayoutType { case .compact: - self.itemSize = 36.0 + minItemsPerRow = 8 + self.nativeItemSize = 36.0 self.verticalSpacing = 9.0 minSpacing = 9.0 case .detailed: - self.itemSize = 76.0 + minItemsPerRow = 5 + self.nativeItemSize = 76.0 self.verticalSpacing = 2.0 minSpacing = 2.0 } @@ -257,8 +261,11 @@ public final class EmojiPagerContentComponent: Component { let itemHorizontalSpace = width - self.containerInsets.left - self.containerInsets.right - self.itemsPerRow = Int((itemHorizontalSpace + minSpacing) / (self.itemSize + minSpacing)) - self.horizontalSpacing = floor((itemHorizontalSpace - self.itemSize * CGFloat(self.itemsPerRow)) / CGFloat(self.itemsPerRow - 1)) + self.itemsPerRow = max(minItemsPerRow, Int((itemHorizontalSpace + minSpacing) / (self.nativeItemSize + minSpacing))) + + self.visibleItemSize = floor((itemHorizontalSpace - CGFloat(self.itemsPerRow - 1) * minSpacing) / CGFloat(self.itemsPerRow)) + + self.horizontalSpacing = floor((itemHorizontalSpace - self.visibleItemSize * CGFloat(self.itemsPerRow)) / CGFloat(self.itemsPerRow - 1)) var verticalGroupOrigin: CGFloat = self.containerInsets.top self.itemGroupLayouts = [] @@ -269,7 +276,7 @@ public final class EmojiPagerContentComponent: Component { } let numRowsInGroup = (itemGroup.itemCount + (self.itemsPerRow - 1)) / self.itemsPerRow - let groupContentSize = CGSize(width: width, height: itemTopOffset + CGFloat(numRowsInGroup) * self.itemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) + let groupContentSize = CGSize(width: width, height: itemTopOffset + CGFloat(numRowsInGroup) * self.visibleItemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) self.itemGroupLayouts.append(ItemGroupLayout( frame: CGRect(origin: CGPoint(x: 0.0, y: verticalGroupOrigin), size: groupContentSize), id: itemGroup.id, @@ -290,12 +297,12 @@ public final class EmojiPagerContentComponent: Component { return CGRect( origin: CGPoint( - x: self.containerInsets.left + CGFloat(column) * (self.itemSize + self.horizontalSpacing), - y: groupLayout.frame.minY + groupLayout.itemTopOffset + CGFloat(row) * (self.itemSize + self.verticalSpacing) + x: self.containerInsets.left + CGFloat(column) * (self.visibleItemSize + self.horizontalSpacing), + y: groupLayout.frame.minY + groupLayout.itemTopOffset + CGFloat(row) * (self.visibleItemSize + self.verticalSpacing) ), size: CGSize( - width: self.itemSize, - height: self.itemSize + width: self.visibleItemSize, + height: self.visibleItemSize ) ) } @@ -310,9 +317,9 @@ public final class EmojiPagerContentComponent: Component { continue } let offsetRect = rect.offsetBy(dx: -self.containerInsets.left, dy: -group.frame.minY - group.itemTopOffset) - var minVisibleRow = Int(floor((offsetRect.minY - self.verticalSpacing) / (self.itemSize + self.verticalSpacing))) + 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.itemSize + self.verticalSpacing))) + 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) @@ -330,6 +337,60 @@ public final class EmojiPagerContentComponent: Component { } } + final class ItemPlaceholderView: UIView { + private let shimmerView: PortalSourceView? + private var placeholderView: PortalView? + private let placeholderMaskLayer: SimpleLayer + + init( + context: AccountContext, + file: TelegramMediaFile, + shimmerView: PortalSourceView?, + color: UIColor?, + size: CGSize + ) { + self.shimmerView = shimmerView + self.placeholderView = PortalView() + self.placeholderMaskLayer = SimpleLayer() + + super.init(frame: CGRect()) + + if let placeholderView = self.placeholderView, let shimmerView = self.shimmerView { + placeholderView.view.clipsToBounds = true + placeholderView.view.layer.mask = self.placeholderMaskLayer + self.addSubview(placeholderView.view) + shimmerView.addPortal(view: placeholderView) + } + + 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: color ?? .black) { + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + + if let _ = color { + strongSelf.layer.contents = image.cgImage + } else { + strongSelf.placeholderMaskLayer.contents = image.cgImage + } + } + } + } + } + + 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) + } + self.placeholderMaskLayer.frame = CGRect(origin: CGPoint(), size: size) + } + } + final class ItemLayer: MultiAnimationRenderTarget { struct Key: Hashable { var groupId: AnyHashable @@ -353,7 +414,8 @@ public final class EmojiPagerContentComponent: Component { } } } - private var displayPlaceholder: Bool = false + private(set) var displayPlaceholder: Bool = false + let onUpdateDisplayPlaceholder: (Bool) -> Void init( item: Item, @@ -366,11 +428,13 @@ public final class EmojiPagerContentComponent: Component { placeholderColor: UIColor, blurredBadgeColor: UIColor, displayPremiumBadgeIfAvailable: Bool, - pointSize: CGSize + pointSize: CGSize, + onUpdateDisplayPlaceholder: @escaping (Bool) -> Void ) { self.item = item self.file = file self.placeholderColor = placeholderColor + self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder let scale = min(2.0, UIScreenScale) let pixelSize = CGSize(width: pointSize.width * scale, height: pointSize.height * scale) @@ -414,17 +478,21 @@ public final class EmojiPagerContentComponent: Component { if attemptSynchronousLoad { if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { - self.displayPlaceholder = true - - if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: self.size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor) { - self.contents = image.cgImage - } + self.updateDisplayPlaceholder(displayPlaceholder: true) } loadAnimation() } else { - let _ = renderer.loadFirstFrame(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { _ in + let _ = renderer.loadFirstFrame(groupId: groupId, 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 dimensions = file.dimensions { @@ -458,7 +526,19 @@ public final class EmojiPagerContentComponent: Component { } override public init(layer: Any) { - preconditionFailure() + guard let layer = layer as? ItemLayer else { + preconditionFailure() + } + + self.item = layer.item + + self.file = layer.file + self.placeholderColor = layer.placeholderColor + self.size = layer.size + + self.onUpdateDisplayPlaceholder = { _ in } + + super.init(layer: layer) } required public init?(coder: NSCoder) { @@ -492,34 +572,65 @@ public final class EmojiPagerContentComponent: Component { } self.displayPlaceholder = displayPlaceholder - let file = self.file - let size = self.size - let placeholderColor = self.placeholderColor + self.onUpdateDisplayPlaceholder(displayPlaceholder) - Queue.concurrentDefaultQueue().async { [weak self] in - if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor) { - Queue.mainQueue().async { - guard let strongSelf = self else { - return - } - - if strongSelf.displayPlaceholder { - strongSelf.contents = image.cgImage + /*if displayPlaceholder { + if self.placeholderView == nil { + self.placeholderView = PortalView() + if let placeholderView = self.placeholderView, let shimmerView = self.shimmerView { + self.addSublayer(placeholderView.view.layer) + placeholderView.view.frame = self.bounds + shimmerView.addPortal(view: placeholderView) + } + } + if self.placeholderMaskLayer == nil { + self.placeholderMaskLayer = SimpleLayer() + self.placeholderView?.view.layer.mask = self.placeholderMaskLayer + } + let file = self.file + let size = self.size + //let placeholderColor = self.placeholderColor + + Queue.concurrentDefaultQueue().async { [weak self] in + if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: .black) { + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + + if strongSelf.displayPlaceholder { + strongSelf.placeholderMaskLayer?.contents = image.cgImage + } } } } - } + } else { + if let placeholderView = self.placeholderView { + self.placeholderView = nil + placeholderView.view.layer.removeFromSuperlayer() + } + if let _ = self.placeholderMaskLayer { + self.placeholderMaskLayer = nil + } + }*/ } } private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { } - private let scrollView: ContentScrollView + private let shimmerHostView: PortalSourceView + private let standaloneShimmerEffect: StandaloneShimmerEffect + private let scrollView: ContentScrollView + private let boundsChangeTrackerLayer = SimpleLayer() + private var effectiveVisibleSize: CGSize = CGSize() + + private var visibleItemPlaceholderViews: [ItemLayer.Key: ItemPlaceholderView] = [:] private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:] private var visibleGroupHeaders: [AnyHashable: ComponentView] = [:] private var ignoreScrolling: Bool = false + private var keepTopPanelVisibleUntilScrollingInput: Bool = false private var component: EmojiPagerContentComponent? private var pagerEnvironment: PagerComponentChildEnvironment? @@ -532,10 +643,24 @@ public final class EmojiPagerContentComponent: Component { private weak var peekController: PeekController? override init(frame: CGRect) { + self.shimmerHostView = PortalSourceView() + + self.standaloneShimmerEffect = StandaloneShimmerEffect() + self.scrollView = ContentScrollView() + self.scrollView.layer.anchorPoint = CGPoint() super.init(frame: frame) + self.shimmerHostView.alpha = 0.0 + self.addSubview(self.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 @@ -546,8 +671,11 @@ public final class EmojiPagerContentComponent: Component { self.scrollView.showsVerticalScrollIndicator = true self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.delegate = self + self.scrollView.clipsToBounds = false self.addSubview(self.scrollView) + //self.clipsToBounds = true + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) /*self.useSublayerTransformForActivation = false @@ -747,7 +875,9 @@ public final class EmojiPagerContentComponent: Component { self.scrollView.setContentOffset(self.scrollView.contentOffset, animated: false) self.ignoreScrolling = wasIgnoringScrollingEvents - self.scrollView.scrollRectToVisible(CGRect(origin: group.frame.origin.offsetBy(dx: 0.0, dy: floor(-itemLayout.verticalGroupSpacing / 2.0)), size: CGSize(width: 1.0, height: self.scrollView.bounds.height)), animated: true) + self.keepTopPanelVisibleUntilScrollingInput = true + + self.scrollView.scrollRectToVisible(CGRect(origin: group.frame.origin.offsetBy(dx: 0.0, dy: floor(-itemLayout.verticalGroupSpacing / 2.0) - 41.0), size: CGSize(width: 1.0, height: self.scrollView.bounds.height)), animated: true) } } } @@ -780,6 +910,11 @@ public final class EmojiPagerContentComponent: Component { 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() @@ -793,7 +928,7 @@ public final class EmojiPagerContentComponent: Component { self.updateVisibleItems(attemptSynchronousLoads: false) - self.updateScrollingOffset(transition: .immediate) + self.updateScrollingOffset(isReset: false, transition: .immediate) } public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer) { @@ -812,21 +947,28 @@ public final class EmojiPagerContentComponent: Component { self.snapScrollingOffsetToInsets() } - private func updateScrollingOffset(transition: Transition) { + 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 { + 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 - self.pagerEnvironment?.onChildScrollingUpdate(PagerComponentChildEnvironment.ContentScrollingUpdate( - relativeOffset: relativeOffset, - absoluteOffsetToTopEdge: offsetToTopEdge, - absoluteOffsetToBottomEdge: offsetToBottomEdge, - isInteracting: isInteracting, - transition: transition - )) + 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) } @@ -855,7 +997,7 @@ public final class EmojiPagerContentComponent: Component { currentBounds.origin.y = self.snappedContentOffset(proposedOffset: currentBounds.minY) transition.setBounds(view: self.scrollView, bounds: currentBounds) - self.updateScrollingOffset(transition: transition) + self.updateScrollingOffset(isReset: false, transition: transition) } private func updateVisibleItems(attemptSynchronousLoads: Bool) { @@ -868,14 +1010,17 @@ public final class EmojiPagerContentComponent: Component { var validIds = Set() var validGroupHeaderIds = Set() - for groupItems in itemLayout.visibleItems(for: self.scrollView.bounds) { - if topVisibleGroupId == nil { - topVisibleGroupId = groupItems.id - } - + let effectiveVisibleBounds = CGRect(origin: self.scrollView.bounds.origin, size: self.effectiveVisibleSize) + let topVisibleDetectionBounds = effectiveVisibleBounds.offsetBy(dx: 0.0, dy: 41.0) + + for groupItems in itemLayout.visibleItems(for: effectiveVisibleBounds) { let itemGroup = component.itemGroups[groupItems.groupIndex] let itemGroupLayout = itemLayout.itemGroupLayouts[groupItems.groupIndex] + if topVisibleGroupId == nil && itemGroupLayout.frame.intersects(topVisibleDetectionBounds) { + topVisibleGroupId = groupItems.id + } + if let title = itemGroup.title { validGroupHeaderIds.insert(itemGroup.id) let groupHeaderView: ComponentView @@ -888,7 +1033,7 @@ public final class EmojiPagerContentComponent: Component { let groupHeaderSize = groupHeaderView.update( transition: .immediate, component: AnyComponent(Text( - text: title, font: Font.medium(12.0), color: theme.chat.inputMediaPanel.stickersSectionTextColor + text: title.uppercased(), font: Font.medium(12.0), color: theme.chat.inputMediaPanel.stickersSectionTextColor )), environment: {}, containerSize: CGSize(width: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right, height: 100.0) @@ -906,14 +1051,21 @@ public final class EmojiPagerContentComponent: Component { let itemId = ItemLayer.Key(groupId: itemGroup.id, fileId: item.file.fileId) validIds.insert(itemId) + let itemDimensions = item.file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0) + let itemNativeFitSize = itemDimensions.fitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) + let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) + + 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: "keyboard-\(Int(itemLayout.itemSize))", + groupId: "keyboard-\(Int(itemLayout.nativeItemSize))", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, cache: component.animationCache, @@ -921,15 +1073,72 @@ public final class EmojiPagerContentComponent: Component { placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), displayPremiumBadgeIfAvailable: true, - pointSize: CGSize(width: itemLayout.itemSize, height: itemLayout.itemSize) + pointSize: itemNativeFitSize, + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder 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( + context: component.context, + file: item.file, + shimmerView: strongSelf.shimmerHostView, + color: nil, + size: itemNativeFitSize + ) + strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView + strongSelf.scrollView.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) + placeholderView.removeFromSuperview() + + strongSelf.updateShimmerIfNeeded() + } + } + } ) self.scrollView.layer.addSublayer(itemLayer) self.visibleItemLayers[itemId] = itemLayer } - let itemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: index) - itemLayer.position = CGPoint(x: itemFrame.midX, y: itemFrame.midY) - itemLayer.bounds = CGRect(origin: CGPoint(), size: itemFrame.size) + 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 itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + let itemBounds = CGRect(origin: CGPoint(), size: itemFrame.size) + if itemLayer.position != itemPosition { + itemLayer.position = itemPosition + } + if itemLayer.bounds != itemBounds { + itemLayer.bounds = CGRect(origin: CGPoint(), size: itemFrame.size) + } + + if let placeholderView = self.visibleItemPlaceholderViews[itemId] { + if placeholderView.layer.position != itemPosition || placeholderView.layer.bounds != itemBounds { + placeholderView.frame = itemFrame + placeholderView.update(size: itemFrame.size) + } + } else if updateItemLayerPlaceholder { + if itemLayer.displayPlaceholder { + itemLayer.onUpdateDisplayPlaceholder(true) + } + } + itemLayer.isVisibleForAnimations = true } } @@ -943,6 +1152,10 @@ public final class EmojiPagerContentComponent: Component { } for id in removedIds { self.visibleItemLayers.removeValue(forKey: id) + + if let view = self.visibleItemPlaceholderViews.removeValue(forKey: id) { + view.removeFromSuperview() + } } var removedGroupHeaderIds: [AnyHashable] = [] @@ -961,14 +1174,31 @@ public final class EmojiPagerContentComponent: Component { } } + private func updateShimmerIfNeeded() { + if self.visibleItemPlaceholderViews.isEmpty { + self.standaloneShimmerEffect.layer = nil + } else { + self.standaloneShimmerEffect.layer = self.shimmerHostView.layer + } + } + func update(component: EmojiPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { self.component = component - self.theme = environment[EntityKeyboardChildEnvironment.self].value.theme - self.activeItemUpdated = environment[EntityKeyboardChildEnvironment.self].value.getContentActiveItemUpdated(component.id) + + let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value + + self.theme = keyboardChildEnvironment.theme + self.activeItemUpdated = keyboardChildEnvironment.getContentActiveItemUpdated(component.id) 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) + var itemGroups: [ItemGroupDescription] = [] for itemGroup in component.itemGroups { itemGroups.append(ItemGroupDescription( @@ -982,7 +1212,28 @@ public final class EmojiPagerContentComponent: Component { self.itemLayout = itemLayout self.ignoreScrolling = true - transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: availableSize)) + 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(attemptSynchronousLoads: false) + } + }) + } + if self.scrollView.contentSize != itemLayout.contentSize { self.scrollView.contentSize = itemLayout.contentSize } @@ -992,7 +1243,7 @@ public final class EmojiPagerContentComponent: Component { self.previousScrollingOffset = ScrollingOffsetState(value: scrollView.contentOffset.y, isDraggingOrDecelerating: scrollView.isDragging || scrollView.isDecelerating) self.ignoreScrolling = false - self.updateVisibleItems(attemptSynchronousLoads: true) + self.updateVisibleItems(attemptSynchronousLoads: !(scrollView.isDragging || scrollView.isDecelerating)) return availableSize } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 0e458561ea..12cba3bc97 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -47,11 +47,14 @@ public final class EntityKeyboardComponent: Component { public let stickerContent: EmojiPagerContentComponent public let gifContent: GifPagerContentComponent public let defaultToEmojiTab: Bool - public let externalTopPanelContainer: UIView? + public let externalTopPanelContainer: PagerExternalTopPanelContainer? public let topPanelExtensionUpdated: (CGFloat, Transition) -> Void - public let hideInputUpdated: (Bool, Transition) -> Void + public let hideInputUpdated: (Bool, Bool, Transition) -> Void + public let switchToTextInput: () -> Void public let makeSearchContainerNode: (EntitySearchContentType) -> EntitySearchContainerNode public let deviceMetrics: DeviceMetrics + public let hiddenInputHeight: CGFloat + public let isExpanded: Bool public init( theme: PresentationTheme, @@ -60,11 +63,14 @@ public final class EntityKeyboardComponent: Component { stickerContent: EmojiPagerContentComponent, gifContent: GifPagerContentComponent, defaultToEmojiTab: Bool, - externalTopPanelContainer: UIView?, + externalTopPanelContainer: PagerExternalTopPanelContainer?, topPanelExtensionUpdated: @escaping (CGFloat, Transition) -> Void, - hideInputUpdated: @escaping (Bool, Transition) -> Void, + hideInputUpdated: @escaping (Bool, Bool, Transition) -> Void, + switchToTextInput: @escaping () -> Void, makeSearchContainerNode: @escaping (EntitySearchContentType) -> EntitySearchContainerNode, - deviceMetrics: DeviceMetrics + deviceMetrics: DeviceMetrics, + hiddenInputHeight: CGFloat, + isExpanded: Bool ) { self.theme = theme self.bottomInset = bottomInset @@ -75,8 +81,11 @@ public final class EntityKeyboardComponent: Component { self.externalTopPanelContainer = externalTopPanelContainer self.topPanelExtensionUpdated = topPanelExtensionUpdated self.hideInputUpdated = hideInputUpdated + self.switchToTextInput = switchToTextInput self.makeSearchContainerNode = makeSearchContainerNode self.deviceMetrics = deviceMetrics + self.hiddenInputHeight = hiddenInputHeight + self.isExpanded = isExpanded } public static func ==(lhs: EntityKeyboardComponent, rhs: EntityKeyboardComponent) -> Bool { @@ -104,6 +113,12 @@ public final class EntityKeyboardComponent: Component { if lhs.deviceMetrics != rhs.deviceMetrics { return false } + if lhs.hiddenInputHeight != rhs.hiddenInputHeight { + return false + } + if lhs.isExpanded != rhs.isExpanded { + return false + } return true } @@ -118,13 +133,14 @@ public final class EntityKeyboardComponent: Component { private var searchComponent: EntitySearchContentComponent? private var topPanelExtension: CGFloat? + private var isTopPanelExpanded: Bool = false override init(frame: CGRect) { self.pagerView = ComponentHostView() super.init(frame: frame) - self.clipsToBounds = true + //self.clipsToBounds = true self.disablesInteractiveTransitionGestureRecognizer = true self.addSubview(self.pagerView) @@ -146,7 +162,8 @@ public final class EntityKeyboardComponent: Component { let gifsContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(component.gifContent))) var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] - topGifItems.append(EntityKeyboardTopPanelComponent.Item( + topGifItems.removeAll() + /*topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: "recent", content: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/RecentTabIcon", @@ -161,7 +178,7 @@ public final class EntityKeyboardComponent: Component { tintColor: component.theme.chat.inputMediaPanel.panelIconColor, maxSize: CGSize(width: 30.0, height: 30.0)) ) - )) + ))*/ contentTopPanels.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, items: topGifItems, @@ -199,20 +216,21 @@ public final class EntityKeyboardComponent: Component { "recent": "Chat/Input/Media/RecentTabIcon", "premium": "Chat/Input/Media/PremiumIcon" ] - if let iconName = iconMapping[id] { + let titleMapping: [String: String] = [ + "recent": "Recent", + "premium": "Premium" + ] + if let iconName = iconMapping[id], let title = titleMapping[id] { topStickerItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.id, - content: AnyComponent(Button( - content: AnyComponent(BundleIconComponent( - name: iconName, - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: CGSize(width: 30.0, height: 30.0) - )), - action: { [weak self] in + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: iconName, + theme: component.theme, + title: title, + pressed: { [weak self] in self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.id) } - ).minSize(CGSize(width: 30.0, height: 30.0)) - ) + )) )) } } else { @@ -224,6 +242,8 @@ public final class EntityKeyboardComponent: Component { file: itemGroup.items[0].file, animationCache: component.stickerContent.animationCache, animationRenderer: component.stickerContent.animationRenderer, + theme: component.theme, + title: itemGroup.title ?? "", pressed: { [weak self] in self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.id) } @@ -277,6 +297,8 @@ public final class EntityKeyboardComponent: Component { file: itemGroup.items[0].file, animationCache: component.emojiContent.animationCache, animationRenderer: component.emojiContent.animationRenderer, + theme: component.theme, + title: itemGroup.title ?? "", pressed: { [weak self] in self?.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.id) } @@ -294,6 +316,20 @@ public final class EntityKeyboardComponent: Component { tintColor: component.theme.chat.inputMediaPanel.panelIconColor, maxSize: nil )))) + 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.inputInteraction.deleteBackwards contentAccessoryRightButtons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(Button( content: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputClearIcon", @@ -301,9 +337,20 @@ public final class EntityKeyboardComponent: Component { maxSize: nil )), action: { - component.emojiContent.inputInteraction.deleteBackwards() + deleteBackwards() } - ).minSize(CGSize(width: 38.0, height: 38.0))))) + ).withHoldAction({ + deleteBackwards() + }).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, @@ -319,7 +366,8 @@ public final class EntityKeyboardComponent: Component { color: component.theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75) )), topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent( - theme: component.theme + theme: component.theme, + overflowHeight: component.hiddenInputHeight )), externalTopPanelContainer: component.externalTopPanelContainer, bottomPanel: AnyComponent(EntityKeyboardBottomPanelComponent( @@ -335,7 +383,13 @@ public final class EntityKeyboardComponent: Component { } strongSelf.topPanelExtensionUpdated(height: panelState.topPanelHeight, transition: transition) }, - hidePanels: self.searchComponent != nil + isTopPanelExpandedUpdated: { [weak self] isExpanded, transition in + guard let strongSelf = self else { + return + } + strongSelf.isTopPanelExpandedUpdated(isExpanded: isExpanded, transition: transition) + }, + panelHideBehavior: panelHideBehavior )), environment: { EntityKeyboardChildEnvironment( @@ -426,6 +480,18 @@ public final class EntityKeyboardComponent: Component { } } + 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 @@ -451,7 +517,7 @@ public final class EntityKeyboardComponent: Component { } ) //self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) - component.hideInputUpdated(true, Transition(animation: .curve(duration: 0.3, curve: .spring))) + component.hideInputUpdated(true, true, Transition(animation: .curve(duration: 0.3, curve: .spring))) } } @@ -464,7 +530,7 @@ public final class EntityKeyboardComponent: Component { } self.searchComponent = nil //self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) - component.hideInputUpdated(false, 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) { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift index e4a6fe549f..60d71d5d6d 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -9,11 +9,14 @@ import Postbox final class EntityKeyboardTopContainerPanelEnvironment: Equatable { let visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + let isExpandedUpdated: (Bool, Transition) -> Void init( - visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)> + visibilityFractionUpdated: ActionSlot<(CGFloat, Transition)>, + isExpandedUpdated: @escaping (Bool, Transition) -> Void ) { self.visibilityFractionUpdated = visibilityFractionUpdated + self.isExpandedUpdated = isExpandedUpdated } static func ==(lhs: EntityKeyboardTopContainerPanelEnvironment, rhs: EntityKeyboardTopContainerPanelEnvironment) -> Bool { @@ -28,17 +31,23 @@ final class EntityKeyboardTopContainerPanelComponent: Component { typealias EnvironmentType = PagerComponentPanelEnvironment let theme: PresentationTheme + let overflowHeight: CGFloat init( - theme: PresentationTheme + theme: PresentationTheme, + overflowHeight: CGFloat ) { self.theme = theme + self.overflowHeight = overflowHeight } static func ==(lhs: EntityKeyboardTopContainerPanelComponent, rhs: EntityKeyboardTopContainerPanelComponent) -> Bool { if lhs.theme !== rhs.theme { return false } + if lhs.overflowHeight != rhs.overflowHeight { + return false + } return true } @@ -46,6 +55,7 @@ final class EntityKeyboardTopContainerPanelComponent: Component { private final class PanelView { let view = ComponentHostView() let visibilityFractionUpdated = ActionSlot<(CGFloat, Transition)>() + var isExpanded: Bool = false } final class View: UIView { @@ -57,8 +67,13 @@ final class EntityKeyboardTopContainerPanelComponent: Component { private var visibilityFraction: CGFloat = 1.0 + private var hasExpandedPanels: Bool = false + override init(frame: CGRect) { super.init(frame: frame) + + self.disablesInteractiveKeyboardGestureRecognizer = true + self.disablesInteractiveTransitionGestureRecognizer = true } required init?(coder: NSCoder) { @@ -94,7 +109,7 @@ final class EntityKeyboardTopContainerPanelComponent: Component { let panel = panelEnvironment.contentTopPanels[index] let indexOffset = index - centralIndex - let panelFrame = CGRect(origin: CGPoint(x: CGFloat(indexOffset) * availableSize.width, y: 0.0), size: CGSize(width: availableSize.width, height: intrinsicHeight)) + 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 @@ -118,12 +133,19 @@ final class EntityKeyboardTopContainerPanelComponent: Component { self.addSubview(panelView.view) } + let panelId = panel.id let _ = panelView.view.update( transition: panelTransition, component: panel.component, environment: { EntityKeyboardTopContainerPanelEnvironment( - visibilityFractionUpdated: panelView.visibilityFractionUpdated + 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 @@ -171,6 +193,45 @@ final class EntityKeyboardTopContainerPanelComponent: Component { 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 + } + panelView.isExpanded = isExpanded + + var hasExpanded = false + for (_, panel) in self.panelViews { + if panel.isExpanded { + hasExpanded = true + break + } + } + + if self.hasExpandedPanels != hasExpanded { + self.hasExpandedPanels = hasExpanded + + self.panelEnvironment?.isExpandedUpdated(self.hasExpandedPanels, transition) + } + } + + 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 { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 1dbf32cdb8..daf3de90ef 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -1,4 +1,5 @@ import Foundation +import SwiftSignalKit import UIKit import Display import ComponentFlow @@ -9,14 +10,17 @@ import Postbox import AnimationCache import MultiAnimationRenderer import AccountContext +import MultilineTextComponent final class EntityKeyboardAnimationTopPanelComponent: Component { - typealias EnvironmentType = Empty + typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment let context: AccountContext let file: TelegramMediaFile let animationCache: AnimationCache let animationRenderer: MultiAnimationRenderer + let theme: PresentationTheme + let title: String let pressed: () -> Void init( @@ -24,12 +28,16 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { file: TelegramMediaFile, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, + theme: PresentationTheme, + title: String, pressed: @escaping () -> Void ) { self.context = context self.file = file self.animationCache = animationCache self.animationRenderer = animationRenderer + self.theme = theme + self.title = title self.pressed = pressed } @@ -46,13 +54,21 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { 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) @@ -73,6 +89,8 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { func update(component: EntityKeyboardAnimationTopPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { self.component = component + let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value + if self.itemLayer == nil { let itemLayer = EmojiPagerContentComponent.View.ItemLayer( item: EmojiPagerContentComponent.Item( @@ -89,15 +107,88 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { placeholderColor: .lightGray, blurredBadgeColor: .clear, displayPremiumBadgeIfAvailable: false, - pointSize: CGSize(width: 28.0, height: 28.0) + pointSize: CGSize(width: 44.0, height: 44.0), + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder in + guard let strongSelf = self else { + return + } + strongSelf.updateDisplayPlaceholder(displayPlaceholder: displayPlaceholder) + } ) self.itemLayer = itemLayer self.layer.addSublayer(itemLayer) - itemLayer.frame = CGRect(origin: CGPoint(), size: CGSize(width: 28.0, height: 28.0)) + + if itemLayer.displayPlaceholder { + self.updateDisplayPlaceholder(displayPlaceholder: true) + } + } + + let iconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 28.0, height: 28.0) + let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) / 2.0), y: 0.0), size: iconSize) + + 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)) itemLayer.isVisibleForAnimations = true } - return CGSize(width: 28.0, height: 28.0) + 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)) + )), + 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), size: titleSize) + transition.setAlpha(view: view, alpha: 1.0) + } + } else if let titleView = self.titleView { + self.titleView = nil + if let view = titleView.view { + transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } + } + + return availableSize + } + + private func updateDisplayPlaceholder(displayPlaceholder: Bool) { + 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 + placeholderView.removeFromSuperview() + } + } } } @@ -110,14 +201,151 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { } } +final class EntityKeyboardIconTopPanelComponent: Component { + typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment + + let imageName: String + let theme: PresentationTheme + let title: String + let pressed: () -> Void + + init( + imageName: String, + theme: PresentationTheme, + title: String, + pressed: @escaping () -> Void + ) { + self.imageName = imageName + self.theme = theme + self.title = title + self.pressed = pressed + } + + static func ==(lhs: EntityKeyboardIconTopPanelComponent, rhs: EntityKeyboardIconTopPanelComponent) -> Bool { + if lhs.imageName != rhs.imageName { + 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?.imageName != component.imageName { + self.iconView.image = generateTintedImage(image: UIImage(bundleImageName: component.imageName), color: component.theme.chat.inputMediaPanel.panelIconColor) + } + + self.component = component + + let nativeIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 28.0, height: 28.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)) + )), + 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), size: titleSize) + transition.setAlpha(view: view, alpha: 1.0) + } + } else if let titleView = self.titleView { + self.titleView = nil + if let view = titleView.view { + transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in + 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 + + init(isExpanded: Bool) { + self.isExpanded = isExpanded + } + + static func ==(lhs: EntityKeyboardTopPanelItemEnvironment, rhs: EntityKeyboardTopPanelItemEnvironment) -> Bool { + if lhs.isExpanded != rhs.isExpanded { + return false + } + return true + } +} + final class EntityKeyboardTopPanelComponent: Component { typealias EnvironmentType = EntityKeyboardTopContainerPanelEnvironment final class Item: Equatable { let id: AnyHashable - let content: AnyComponent + let content: AnyComponent - init(id: AnyHashable, content: AnyComponent) { + init(id: AnyHashable, content: AnyComponent) { self.id = id self.content = content } @@ -165,34 +393,42 @@ final class EntityKeyboardTopPanelComponent: Component { final class View: UIView, UIScrollViewDelegate { private struct ItemLayout { let sideInset: CGFloat = 7.0 - let itemSize: CGFloat = 32.0 - let innerItemSize: CGFloat = 28.0 + let itemSize: CGSize + let innerItemSize: CGSize let itemSpacing: CGFloat = 15.0 let itemCount: Int let contentSize: CGSize + let isExpanded: Bool - init(itemCount: Int) { + init(itemCount: Int, isExpanded: Bool, height: CGFloat) { + self.isExpanded = isExpanded + self.itemSize = self.isExpanded ? CGSize(width: 54.0, height: 68.0) : CGSize(width: 32.0, height: 32.0) + self.innerItemSize = self.isExpanded ? CGSize(width: 50.0, height: 62.0) : CGSize(width: 28.0, height: 28.0) self.itemCount = itemCount - self.contentSize = CGSize(width: sideInset * 2.0 + CGFloat(itemCount) * self.itemSize + CGFloat(max(0, itemCount - 1)) * itemSpacing, height: 41.0) + self.contentSize = CGSize(width: sideInset * 2.0 + CGFloat(itemCount) * self.itemSize.width + CGFloat(max(0, itemCount - 1)) * itemSpacing, height: height) } func containerFrame(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)) + return CGRect(origin: CGPoint(x: sideInset + CGFloat(index) * (self.itemSize.width + self.itemSpacing), y: floor((self.contentSize.height - self.itemSize.height) / 2.0)), size: self.itemSize) + } + + func contentFrame(containerFrame: CGRect) -> CGRect { + var frame = containerFrame + frame.origin.x += floor((self.itemSize.width - self.innerItemSize.width)) / 2.0 + frame.origin.y += floor((self.itemSize.height - self.innerItemSize.height)) / 2.0 + frame.size = self.innerItemSize + return frame } func contentFrame(at index: Int) -> CGRect { - var frame = self.containerFrame(at: index) - frame.origin.x += floor((self.itemSize - self.innerItemSize)) / 2.0 - frame.origin.y += floor((self.itemSize - self.innerItemSize)) / 2.0 - frame.size = CGSize(width: self.innerItemSize, height: self.innerItemSize) - return frame + return self.contentFrame(containerFrame: self.containerFrame(at: index)) } func visibleItemRange(for rect: CGRect) -> (minIndex: Int, maxIndex: Int) { let offsetRect = rect.offsetBy(dx: -self.sideInset, dy: 0.0) - var minVisibleColumn = Int(floor((offsetRect.minX - self.itemSpacing) / (self.itemSize + self.itemSpacing))) + var minVisibleColumn = Int(floor((offsetRect.minX - self.itemSpacing) / (self.itemSize.width + self.itemSpacing))) minVisibleColumn = max(0, minVisibleColumn) - let maxVisibleColumn = Int(ceil((offsetRect.maxX - self.itemSpacing) / (self.itemSize + self.itemSpacing))) + let maxVisibleColumn = Int(ceil((offsetRect.maxX - self.itemSpacing) / (self.itemSize.width + self.itemSpacing))) let minVisibleIndex = minVisibleColumn let maxVisibleIndex = min(maxVisibleColumn, self.itemCount - 1) @@ -202,15 +438,23 @@ final class EntityKeyboardTopPanelComponent: Component { } private let scrollView: UIScrollView - private var itemViews: [AnyHashable: ComponentHostView] = [:] + private var itemViews: [AnyHashable: ComponentHostView] = [:] private var highlightedIconBackgroundView: UIView private var itemLayout: ItemLayout? private var ignoreScrolling: Bool = false + private var isDragging: Bool = false + private var draggingStoppedTimer: SwiftSignalKit.Timer? + + private var isExpanded: Bool = false + private var visibilityFraction: CGFloat = 1.0 + private var activeContentItemId: AnyHashable? + private var component: EntityKeyboardTopPanelComponent? + private var environment: EntityKeyboardTopContainerPanelEnvironment? override init(frame: CGRect) { self.scrollView = UIScrollView() @@ -222,7 +466,9 @@ final class EntityKeyboardTopPanelComponent: Component { 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 } @@ -236,6 +482,8 @@ final class EntityKeyboardTopPanelComponent: Component { self.scrollView.addSubview(self.highlightedIconBackgroundView) + self.clipsToBounds = true + self.disablesInteractiveTransitionGestureRecognizerNow = { [weak self] in guard let strongSelf = self else { return false @@ -253,38 +501,98 @@ final class EntityKeyboardTopPanelComponent: Component { return } - self.updateVisibleItems(attemptSynchronousLoads: false) + self.updateVisibleItems(attemptSynchronousLoads: false, transition: .immediate) } - private func updateVisibleItems(attemptSynchronousLoads: Bool) { + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + self.updateIsDragging(true) + } + + public func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + if !decelerate { + self.updateIsDragging(false) + } + } + + public func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) { + self.updateIsDragging(false) + } + + private func updateIsDragging(_ isDragging: Bool) { + if !isDragging { + if !self.isDragging { + 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.isDragging = 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.isDragging { + self.isDragging = true + + guard let environment = self.environment else { + return + } + environment.isExpandedUpdated(true, Transition(animation: .curve(duration: 0.3, curve: .spring))) + } + } + } + + private func updateVisibleItems(attemptSynchronousLoads: Bool, transition: Transition) { guard let component = self.component, let itemLayout = self.itemLayout else { return } + var visibleBounds = self.scrollView.bounds + visibleBounds.size.width += 200.0 + var validIds = Set() - let visibleItemRange = itemLayout.visibleItemRange(for: self.scrollView.bounds) + let visibleItemRange = itemLayout.visibleItemRange(for: visibleBounds) if !component.items.isEmpty && visibleItemRange.maxIndex >= visibleItemRange.minIndex { for index in visibleItemRange.minIndex ... visibleItemRange.maxIndex { let item = component.items[index] validIds.insert(item.id) - let itemView: ComponentHostView + var itemTransition = transition + let itemView: ComponentHostView if let current = self.itemViews[item.id] { itemView = current } else { - itemView = ComponentHostView() + itemTransition = .immediate + itemView = ComponentHostView() self.scrollView.addSubview(itemView) self.itemViews[item.id] = itemView } let itemOuterFrame = itemLayout.contentFrame(at: index) let itemSize = itemView.update( - transition: .immediate, + transition: itemTransition, component: item.content, - environment: {}, + environment: { + EntityKeyboardTopPanelItemEnvironment(isExpanded: itemLayout.isExpanded) + }, containerSize: itemOuterFrame.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) + 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) + /*if index == visibleItemRange.minIndex, !itemTransition.animation.isImmediate { + print("\(index): \(itemView.frame) -> \(itemFrame)") + }*/ + itemTransition.setFrame(view: itemView, frame: itemFrame) } } var removedIds: [AnyHashable] = [] @@ -305,22 +613,77 @@ final class EntityKeyboardTopPanelComponent: Component { } self.component = component - let intrinsicHeight: CGFloat = 41.0 + let panelEnvironment = environment[EntityKeyboardTopContainerPanelEnvironment.self].value + self.environment = panelEnvironment + + let isExpanded = availableSize.height > 41.0 + let wasExpanded = self.isExpanded + self.isExpanded = isExpanded + + let intrinsicHeight: CGFloat = availableSize.height let height = intrinsicHeight - let itemLayout = ItemLayout(itemCount: component.items.count) + let previousItemLayout = self.itemLayout + let itemLayout = ItemLayout(itemCount: component.items.count, isExpanded: isExpanded, height: availableSize.height) self.itemLayout = itemLayout self.ignoreScrolling = true - transition.setFrame(view: self.scrollView, frame: CGRect(origin: CGPoint(), size: CGSize(width: availableSize.width, height: intrinsicHeight))) + + var updatedBounds: CGRect? + if wasExpanded != isExpanded, let previousItemLayout = previousItemLayout { + var visibleBounds = self.scrollView.bounds + visibleBounds.size.width += 200.0 + + let previousVisibleRange = previousItemLayout.visibleItemRange(for: visibleBounds) + if previousVisibleRange.minIndex <= previousVisibleRange.maxIndex { + let previousItemFrame = previousItemLayout.containerFrame(at: previousVisibleRange.minIndex) + let updatedItemFrame = itemLayout.containerFrame(at: previousVisibleRange.minIndex) + + let previousDistanceToItemFraction = (previousItemFrame.minX - self.scrollView.bounds.minX) / previousItemFrame.width + let newBounds = CGRect(origin: CGPoint(x: updatedItemFrame.minX - floor(previousDistanceToItemFraction * updatedItemFrame.width), y: 0.0), size: availableSize) + updatedBounds = newBounds + + var updatedVisibleBounds = newBounds + updatedVisibleBounds.size.width += 200.0 + let updatedVisibleRange = itemLayout.visibleItemRange(for: updatedVisibleBounds) + + let baseFrame = CGRect(origin: CGPoint(x: updatedItemFrame.minX, y: previousItemFrame.minY), size: previousItemFrame.size) + for index in updatedVisibleRange.minIndex ..< updatedVisibleRange.maxIndex { + let indexDifference = index - previousVisibleRange.minIndex + if let itemView = self.itemViews[component.items[index].id] { + let itemContainerOriginX = baseFrame.minX + CGFloat(indexDifference) * (previousItemLayout.itemSize.width + previousItemLayout.itemSpacing) + let itemContainerFrame = CGRect(origin: CGPoint(x: itemContainerOriginX, y: baseFrame.minY), size: baseFrame.size) + let itemOuterFrame = previousItemLayout.contentFrame(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 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: true) + self.updateVisibleItems(attemptSynchronousLoads: !(self.scrollView.isDragging || self.scrollView.isDecelerating), transition: transition) - environment[EntityKeyboardTopContainerPanelEnvironment.self].value.visibilityFractionUpdated.connect { [weak self] (fraction, transition) in + if let activeContentItemId = self.activeContentItemId { + if let index = component.items.firstIndex(where: { $0.id == activeContentItemId }) { + let itemFrame = itemLayout.containerFrame(at: index) + transition.setPosition(view: self.highlightedIconBackgroundView, position: CGPoint(x: itemFrame.midX, y: itemFrame.midY)) + transition.setBounds(view: self.highlightedIconBackgroundView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + } + } + 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 } @@ -359,6 +722,8 @@ final class EntityKeyboardTopPanelComponent: Component { guard let component = self.component, let itemLayout = self.itemLayout else { return } + + self.activeContentItemId = itemId var found = false for i in 0 ..< component.items.count { @@ -366,7 +731,10 @@ final class EntityKeyboardTopPanelComponent: Component { found = true self.highlightedIconBackgroundView.isHidden = false let itemFrame = itemLayout.containerFrame(at: i) - transition.setFrame(view: self.highlightedIconBackgroundView, frame: itemFrame) + transition.setPosition(view: self.highlightedIconBackgroundView, position: CGPoint(x: itemFrame.midX, y: itemFrame.midY)) + transition.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 } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index 630000f39b..02936915b6 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -464,6 +464,7 @@ public final class GifPagerContentComponent: Component { relativeOffset: relativeOffset, absoluteOffsetToTopEdge: offsetToTopEdge, absoluteOffsetToBottomEdge: offsetToBottomEdge, + isReset: false, isInteracting: isInteracting, transition: transition )) diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index 34a79ff6e8..3354285be9 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -3,6 +3,7 @@ import UIKit import SwiftSignalKit import Display import AnimationCache +import Accelerate public protocol MultiAnimationRenderer: AnyObject { func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable @@ -36,6 +37,7 @@ open class MultiAnimationRenderTarget: SimpleLayer { private final class FrameGroup { let image: UIImage + let badgeImage: UIImage? let size: CGSize let timestamp: Double @@ -50,6 +52,27 @@ private final class FrameGroup { firstFrame.data.withUnsafeBytes { bytes -> Void in memcpy(context.bytes, bytes.baseAddress!.advanced(by: firstFrame.range.lowerBound), height * bytesPerRow) + + /*var sourceBuffer = vImage_Buffer() + sourceBuffer.width = UInt(width) + sourceBuffer.height = UInt(height) + sourceBuffer.data = UnsafeMutableRawPointer(mutating: bytes.baseAddress!.advanced(by: firstFrame.range.lowerBound)) + sourceBuffer.rowBytes = bytesPerRow + + var destinationBuffer = vImage_Buffer() + destinationBuffer.width = UInt(32) + destinationBuffer.height = UInt(32) + destinationBuffer.data = context.bytes + destinationBuffer.rowBytes = bytesPerRow + + vImageBoxConvolve_ARGB8888(&sourceBuffer, + &destinationBuffer, + nil, + UInt(width - 32 - 16), UInt(height - 32 - 16), + UInt32(31), + UInt32(31), + nil, + vImage_Flags(kvImageEdgeExtend))*/ } guard let image = context.generateImage() else { @@ -59,6 +82,7 @@ private final class FrameGroup { self.image = image self.size = CGSize(width: CGFloat(width), height: CGFloat(height)) self.timestamp = timestamp + self.badgeImage = nil } } } 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..28fd472ac9 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "planet.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/planet.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/planet.pdf new file mode 100644 index 0000000000..c2225439d8 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/planet.pdf @@ -0,0 +1,255 @@ +%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 3.500000 1.839844 cm +0.000000 0.000000 0.000000 scn +22.170000 13.160156 m +22.170000 7.267279 17.392878 2.490156 11.500000 2.490156 c +11.500000 0.830156 l +18.309671 0.830156 23.830000 6.350485 23.830000 13.160156 c +22.170000 13.160156 l +h +11.500000 2.490156 m +5.607122 2.490156 0.830000 7.267279 0.830000 13.160156 c +-0.830000 13.160156 l +-0.830000 6.350485 4.690329 0.830156 11.500000 0.830156 c +11.500000 2.490156 l +h +0.830000 13.160156 m +0.830000 19.053034 5.607122 23.830156 11.500000 23.830156 c +11.500000 25.490156 l +4.690329 25.490156 -0.830000 19.969828 -0.830000 13.160156 c +0.830000 13.160156 l +h +11.500000 23.830156 m +17.392878 23.830156 22.170000 19.053034 22.170000 13.160156 c +23.830000 13.160156 l +23.830000 19.969828 18.309671 25.490156 11.500000 25.490156 c +11.500000 23.830156 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 8.500000 1.839844 cm +0.000000 0.000000 0.000000 scn +12.170000 13.160156 m +12.170000 10.100716 11.467313 7.371819 10.373627 5.436836 c +9.265684 3.476629 7.863927 2.490156 6.500000 2.490156 c +6.500000 0.830156 l +8.725924 0.830156 10.574167 2.418047 11.818761 4.620020 c +13.077613 6.847219 13.830000 9.868322 13.830000 13.160156 c +12.170000 13.160156 l +h +6.500000 2.490156 m +5.136073 2.490156 3.734316 3.476629 2.626373 5.436836 c +1.532687 7.371819 0.830000 10.100716 0.830000 13.160156 c +-0.830000 13.160156 l +-0.830000 9.868322 -0.077613 6.847219 1.181239 4.620020 c +2.425833 2.418047 4.274076 0.830156 6.500000 0.830156 c +6.500000 2.490156 l +h +0.830000 13.160156 m +0.830000 16.219597 1.532687 18.948494 2.626373 20.883476 c +3.734316 22.843683 5.136073 23.830156 6.500000 23.830156 c +6.500000 25.490156 l +4.274076 25.490156 2.425833 23.902266 1.181239 21.700291 c +-0.077613 19.473093 -0.830000 16.451990 -0.830000 13.160156 c +0.830000 13.160156 l +h +6.500000 23.830156 m +7.863927 23.830156 9.265684 22.843683 10.373627 20.883476 c +11.467313 18.948494 12.170000 16.219597 12.170000 13.160156 c +13.830000 13.160156 l +13.830000 16.451990 13.077613 19.473093 11.818761 21.700291 c +10.574167 23.902266 8.725924 25.490156 6.500000 25.490156 c +6.500000 23.830156 l +h +f +n +Q +q +1.000000 0.000000 -0.000000 1.000000 15.000000 3.500000 cm +0.000000 0.000000 0.000000 scn +-0.830000 23.000000 m +-0.830000 0.000000 l +0.830000 0.000000 l +0.830000 23.000000 l +-0.830000 23.000000 l +h +f +n +Q +q +0.000000 1.000000 -1.000000 0.000000 5.160156 15.000000 cm +0.000000 0.000000 0.000000 scn +-0.830000 1.660156 m +-0.830000 -21.339844 l +0.830000 -21.339844 l +0.830000 1.660156 l +-0.830000 1.660156 l +h +f +n +Q +q +0.000000 1.000000 -1.000000 0.000000 9.019043 8.000000 cm +0.000000 0.000000 0.000000 scn +0.000000 3.519043 m +-0.686377 3.052367 -0.686606 3.052704 -0.686827 3.053029 c +-0.686890 3.053123 -0.687103 3.053437 -0.687230 3.053624 c +-0.687484 3.053999 -0.687707 3.054330 -0.687901 3.054617 c +-0.688287 3.055190 -0.688552 3.055586 -0.688699 3.055805 c +-0.688991 3.056243 -0.688808 3.055973 -0.688163 3.054991 c +-0.686874 3.053027 -0.683741 3.048217 -0.678884 3.040542 c +-0.669169 3.025192 -0.652556 2.998377 -0.630008 2.959931 c +-0.584915 2.883047 -0.516061 2.759615 -0.431147 2.588317 c +-0.261366 2.245815 -0.027114 1.711416 0.209833 0.974417 c +0.683340 -0.498374 1.170000 -2.787649 1.170000 -5.980957 c +2.830000 -5.980957 l +2.830000 -2.615824 2.316660 -0.155099 1.790166 1.482499 c +1.527114 2.300695 1.261366 2.911589 1.056147 3.325581 c +0.953561 3.532529 0.866165 3.690144 0.801883 3.799746 c +0.769744 3.854543 0.743388 3.897330 0.723805 3.928271 c +0.714015 3.943742 0.705917 3.956251 0.699638 3.965818 c +0.696498 3.970602 0.693813 3.974651 0.691598 3.977967 c +0.690490 3.979625 0.689500 3.981099 0.688629 3.982391 c +0.688194 3.983037 0.687788 3.983638 0.687413 3.984192 c +0.687225 3.984469 0.686966 3.984851 0.686872 3.984990 c +0.686621 3.985360 0.686377 3.985719 0.000000 3.519043 c +h +1.170000 -5.980957 m +1.170000 -9.174265 0.683340 -11.463540 0.209833 -12.936331 c +-0.027114 -13.673330 -0.261366 -14.207729 -0.431147 -14.550232 c +-0.516061 -14.721529 -0.584915 -14.844961 -0.630008 -14.921844 c +-0.652556 -14.960291 -0.669169 -14.987106 -0.678884 -15.002457 c +-0.683741 -15.010132 -0.686874 -15.014940 -0.688163 -15.016905 c +-0.688808 -15.017887 -0.688991 -15.018158 -0.688699 -15.017719 c +-0.688552 -15.017500 -0.688287 -15.017103 -0.687901 -15.016531 c +-0.687707 -15.016245 -0.687484 -15.015913 -0.687230 -15.015539 c +-0.687103 -15.015350 -0.686890 -15.015036 -0.686827 -15.014942 c +-0.686606 -15.014618 -0.686377 -15.014280 0.000000 -15.480957 c +0.686377 -15.947634 0.686621 -15.947273 0.686872 -15.946903 c +0.686966 -15.946766 0.687225 -15.946383 0.687413 -15.946106 c +0.687788 -15.945551 0.688194 -15.944952 0.688629 -15.944305 c +0.689500 -15.943014 0.690490 -15.941538 0.691598 -15.939880 c +0.693813 -15.936565 0.696498 -15.932516 0.699638 -15.927732 c +0.705917 -15.918165 0.714015 -15.905657 0.723805 -15.890184 c +0.743388 -15.859243 0.769744 -15.816458 0.801883 -15.761660 c +0.866165 -15.652058 0.953561 -15.494444 1.056147 -15.287495 c +1.261366 -14.873503 1.527114 -14.262609 1.790166 -13.444414 c +2.316660 -11.806815 2.830000 -9.346090 2.830000 -5.980957 c +1.170000 -5.980957 l +h +f +n +Q +q +0.000000 -1.000000 1.000000 0.000000 20.980957 22.000000 cm +0.000000 0.000000 0.000000 scn +0.000000 3.519043 m +-0.686377 3.052367 -0.686606 3.052704 -0.686827 3.053029 c +-0.686890 3.053123 -0.687103 3.053437 -0.687230 3.053624 c +-0.687484 3.053999 -0.687707 3.054330 -0.687901 3.054617 c +-0.688287 3.055190 -0.688552 3.055586 -0.688699 3.055805 c +-0.688991 3.056243 -0.688808 3.055973 -0.688163 3.054991 c +-0.686874 3.053027 -0.683741 3.048217 -0.678884 3.040542 c +-0.669169 3.025192 -0.652556 2.998377 -0.630008 2.959931 c +-0.584915 2.883047 -0.516061 2.759615 -0.431147 2.588317 c +-0.261366 2.245815 -0.027114 1.711416 0.209833 0.974417 c +0.683340 -0.498374 1.170000 -2.787649 1.170000 -5.980957 c +2.830000 -5.980957 l +2.830000 -2.615824 2.316660 -0.155099 1.790166 1.482499 c +1.527114 2.300695 1.261366 2.911589 1.056147 3.325581 c +0.953561 3.532529 0.866165 3.690144 0.801883 3.799746 c +0.769744 3.854543 0.743388 3.897330 0.723805 3.928271 c +0.714015 3.943742 0.705917 3.956251 0.699638 3.965818 c +0.696498 3.970602 0.693813 3.974651 0.691598 3.977967 c +0.690490 3.979625 0.689500 3.981099 0.688629 3.982391 c +0.688194 3.983037 0.687788 3.983638 0.687413 3.984192 c +0.687225 3.984469 0.686966 3.984851 0.686872 3.984990 c +0.686621 3.985360 0.686377 3.985719 0.000000 3.519043 c +h +1.170000 -5.980957 m +1.170000 -9.174265 0.683340 -11.463540 0.209833 -12.936331 c +-0.027114 -13.673330 -0.261366 -14.207729 -0.431147 -14.550232 c +-0.516061 -14.721529 -0.584915 -14.844961 -0.630008 -14.921844 c +-0.652556 -14.960291 -0.669169 -14.987106 -0.678884 -15.002457 c +-0.683741 -15.010132 -0.686874 -15.014940 -0.688163 -15.016905 c +-0.688808 -15.017887 -0.688991 -15.018158 -0.688699 -15.017719 c +-0.688552 -15.017500 -0.688287 -15.017103 -0.687901 -15.016531 c +-0.687707 -15.016245 -0.687484 -15.015913 -0.687230 -15.015539 c +-0.687103 -15.015350 -0.686890 -15.015036 -0.686827 -15.014942 c +-0.686606 -15.014618 -0.686377 -15.014280 0.000000 -15.480957 c +0.686377 -15.947634 0.686621 -15.947273 0.686872 -15.946903 c +0.686966 -15.946766 0.687225 -15.946383 0.687413 -15.946106 c +0.687788 -15.945551 0.688194 -15.944952 0.688629 -15.944305 c +0.689500 -15.943014 0.690490 -15.941538 0.691598 -15.939880 c +0.693813 -15.936565 0.696498 -15.932516 0.699638 -15.927732 c +0.705917 -15.918165 0.714015 -15.905657 0.723805 -15.890184 c +0.743388 -15.859243 0.769744 -15.816458 0.801883 -15.761660 c +0.866165 -15.652058 0.953561 -15.494444 1.056147 -15.287495 c +1.261366 -14.873503 1.527114 -14.262609 1.790166 -13.444414 c +2.316660 -11.806815 2.830000 -9.346090 2.830000 -5.980957 c +1.170000 -5.980957 l +h +f +n +Q + +endstream +endobj + +3 0 obj + 7785 +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 +0000007875 00000 n +0000007898 00000 n +0000008071 00000 n +0000008145 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +8204 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/anim_smiletosticker.json b/submodules/TelegramUI/Resources/Animations/anim_smiletosticker.json new file mode 100644 index 0000000000..26d136207a --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/anim_stickertosmile.json b/submodules/TelegramUI/Resources/Animations/anim_stickertosmile.json new file mode 100644 index 0000000000..1f209a5db8 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/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/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 86f724661d..34a5d34f2a 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -532,7 +532,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { return } - strongSelf.requestLayout(transition) + if transition.isAnimated { + strongSelf.scheduleLayoutTransitionRequest(transition) + } else { + strongSelf.requestLayout(transition) + } } self.addSubnode(self.inputPanelContainerNode) @@ -592,6 +596,12 @@ 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.inputMediaNodeDataDisposable = (self.inputMediaNodeDataPromise.get() |> deliverOnMainQueue).start(next: { [weak self] value in @@ -1056,7 +1066,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) + 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 @@ -1066,7 +1076,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } 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) + 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 { @@ -1074,7 +1084,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) + 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 { @@ -1085,7 +1095,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) + 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 { @@ -1093,7 +1103,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) + 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 { @@ -1142,7 +1152,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var maximumInputNodeHeight = layout.size.height - max(layout.statusBarHeight ?? 0.0, layout.safeInsets.top) - 10.0 if let inputPanelSize = inputPanelSize { - maximumInputNodeHeight -= inputPanelSize.height + if let inputNode = self.inputNode, inputNode.hideInput, !inputNode.adjustLayoutForHiddenInput { + maximumInputNodeHeight -= inputPanelNodeBaseHeight + } else { + maximumInputNodeHeight -= inputPanelSize.height + } } if let secondaryInputPanelSize = secondaryInputPanelSize { maximumInputNodeHeight -= secondaryInputPanelSize.height @@ -1210,13 +1224,13 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } - if inputNode.hideInput, let inputPanelSize = inputPanelSize { + 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) + 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) @@ -1267,7 +1281,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.historyNode.isSelectionGestureEnabled = isSelectionEnabled 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))) @@ -1358,7 +1372,11 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 { @@ -1384,7 +1402,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } if let inputNode = self.inputNode { - if inputNode.hideInput { + if inputNode.hideInput && inputNode.adjustLayoutForHiddenInput { inputPanelsHeight = 0.0 } } @@ -1963,7 +1981,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { private func updateInputPanelBackgroundExpansion(transition: ContainedViewLayoutTransition) { if let inputNode = self.inputNode { - if inputNode.hideInput { + if inputNode.hideInput && inputNode.adjustLayoutForHiddenInput { self.storedHideInputExpanded = self.inputPanelContainerNode.expansionFraction == 1.0 self.inputPanelContainerNode.expand() } else { @@ -2270,6 +2288,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { self.inputPanelContainerNode.collapse() if let inputNode = self.inputNode { inputNode.hideInput = false + inputNode.adjustLayoutForHiddenInput = false if let inputNode = inputNode as? ChatEntityKeyboardInputNode { inputNode.markInputCollapsed() } @@ -2344,7 +2363,7 @@ 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) } } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index ec3ec5f6db..f5a5170437 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -14,6 +14,7 @@ import TelegramCore import ComponentDisplayAdapters import SettingsUI import TextFormat +import PagerComponent final class ChatEntityKeyboardInputNode: ChatInputNode { struct InputData: Equatable { @@ -215,11 +216,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var title: String? if group.id == AnyHashable("recent") { //TODO:localize - title = "Recently Used".uppercased() + title = "Recently Used" } else { for (id, info, _) in view.collectionInfos { if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { - title = info.title.uppercased() + title = info.title break } } @@ -396,17 +397,17 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var title: String? if group.id == AnyHashable("saved") { //TODO:localize - title = "Saved".uppercased() + title = "Saved" } else if group.id == AnyHashable("recent") { //TODO:localize - title = "Recently Used".uppercased() + title = "Recently Used" } else if group.id == AnyHashable("premium") { //TODO:localize - title = "Premium".uppercased() + title = "Premium" } else { for (id, info, _) in view.collectionInfos { if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { - title = info.title.uppercased() + title = info.title break } } @@ -462,7 +463,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private var isMarkInputCollapsed: Bool = false - 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)? + var externalTopPanelContainerImpl: PagerExternalTopPanelContainer? + override var externalTopPanelContainer: UIView? { + return self.externalTopPanelContainerImpl + } + + 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)? init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction) { self.context = context @@ -477,7 +483,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.view.addSubview(self.entityKeyboardView) - self.externalTopPanelContainer = SparseContainerView() + self.externalTopPanelContainerImpl = PagerExternalTopPanelContainer() self.inputDataDisposable = (updatedInputData |> deliverOnMainQueue).start(next: { [weak self] inputData in @@ -530,20 +536,25 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } private func performLayout() { - guard let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) = self.currentState else { + guard let (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible, isExpanded) = self.currentState else { return } - 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) } - 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) { - self.currentState = (width, leftInset, rightInset, bottomInset, standardInputHeight, inputHeight, maximumHeight, inputPanelHeight, interfaceState, deviceMetrics, isVisible) + 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 wasMarkedInputCollapsed = self.isMarkInputCollapsed self.isMarkInputCollapsed = false let expandedHeight = standardInputHeight + self.expansionFraction * (maximumHeight - 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! @@ -564,7 +575,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { stickerContent: self.currentInputData.stickers, gifContent: self.currentInputData.gifs, defaultToEmojiTab: self.defaultToEmojiTab, - externalTopPanelContainer: self.externalTopPanelContainer, + externalTopPanelContainer: self.externalTopPanelContainerImpl, topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in guard let strongSelf = self else { return @@ -574,15 +585,24 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { strongSelf.topBackgroundExtensionUpdated?(transition.containedViewLayoutTransition) } }, - hideInputUpdated: { [weak self] hideInput, transition in + hideInputUpdated: { [weak self] hideInput, adjustLayout, transition in guard let strongSelf = self else { return } - if strongSelf.hideInput != hideInput { + if strongSelf.hideInput != hideInput || strongSelf.adjustLayoutForHiddenInput != adjustLayout { strongSelf.hideInput = hideInput + strongSelf.adjustLayoutForHiddenInput = adjustLayout strongSelf.hideInputUpdated?(transition.containedViewLayoutTransition) } }, + switchToTextInput: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.controllerInteraction.updateInputMode { _ in + return .text + } + }, makeSearchContainerNode: { content in let mappedMode: ChatMediaInputSearchMode switch content { @@ -605,7 +625,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } ) }, - deviceMetrics: deviceMetrics + deviceMetrics: deviceMetrics, + hiddenInputHeight: hiddenInputHeight, + isExpanded: isExpanded )), environment: {}, containerSize: CGSize(width: width, height: expandedHeight) 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/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index cf978d6891..311f6a0a8d 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -11,18 +11,21 @@ class ChatInputNode: ASDisplayNode { return .single(Void()) } - var externalTopPanelContainer: UIView? + var externalTopPanelContainer: UIView? { + return nil + } var topBackgroundExtension: CGFloat = 41.0 var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> Void)? var hideInput: Bool = false + var adjustLayoutForHiddenInput: Bool = false var hideInputUpdated: ((ContainedViewLayoutTransition) -> Void)? var expansionFraction: CGFloat = 0.0 var expansionFractionUpdated: ((ContainedViewLayoutTransition) -> 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) { + 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/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index 68d107097c..a275b87060 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift @@ -302,6 +302,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)) @@ -318,7 +321,7 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte accessoryItems.append(.commands) } - accessoryItems.append(.stickers(stickersEnabled)) + accessoryItems.append(.stickers(isEnabled: stickersEnabled, isEmoji: stickersAreEmoji)) if isTextEmpty, let message = chatPresentationInterfaceState.keyboardButtonsMessage, let _ = message.visibleButtonKeyboardMarkup, chatPresentationInterfaceState.interfaceState.messageActionsState.dismissedButtonKeyboardMessageId != message.id { accessoryItems.append(.inputButtons) diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index 4870710465..fbcf89e302 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -577,7 +577,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 @@ -1473,7 +1473,7 @@ final class ChatMediaInputNode: ChatInputNode { } }))) - if let (_, _, _, _, _, _, _, _, interfaceState, _, _) = strongSelf.validLayout { + if let (_, _, _, _, _, _, _, _, interfaceState, _, _, _) = strongSelf.validLayout { var isScheduledMessages = false if case .scheduledMessages = interfaceState.subject { isScheduledMessages = true @@ -1595,7 +1595,7 @@ final class ChatMediaInputNode: ChatInputNode { |> 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 @@ -1747,7 +1747,7 @@ final class ChatMediaInputNode: ChatInputNode { |> 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 @@ -1922,8 +1922,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 +1940,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 +2179,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 +2545,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 +2554,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 +2570,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 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/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/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index b66b0bb07a..b5c56c774e 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -355,8 +355,9 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { var updatedAttributes: [NSAttributedString.Key: Any] = currentDict updatedAttributes[NSAttributedString.Key.foregroundColor] = UIColor.clear.cgColor updatedAttributes[NSAttributedString.Key("Attribute__EmbeddedItem")] = InlineStickerItem(emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId)) + updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId) - let insertString = NSAttributedString(string: "[\u{00a0}\u{00a0}\u{00a0}]", attributes: updatedAttributes) + let insertString = NSAttributedString(string: updatedString.attributedSubstring(from: range).string, attributes: updatedAttributes) updatedString.replaceCharacters(in: range, with: insertString) } attributedText = updatedString 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/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/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index dbccddb807..76487a0605 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -25,17 +25,25 @@ 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 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.iconImageNode = ASImageNode() let (image, text, accessibilityLabel, alpha, insets) = AccessoryItemIconButtonNode.imageAndInsets(item: item, theme: theme, strings: strings) @@ -46,7 +54,13 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.isAccessibilityElement = true self.accessibilityTraits = [.button] - self.addSubnode(self.imageNode) + self.iconImageNode.isUserInteractionEnabled = false + self.addSubnode(self.iconImageNode) + + if case .stickers = item { + self.iconImageNode.isHidden = true + self.animationView = ComponentView() + } if let text = text { self.setAttributedTitle(NSAttributedString(string: text, font: accessoryButtonFont, textColor: theme.chat.inputPanel.inputControlColor), for: .normal) @@ -54,8 +68,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 @@ -74,6 +88,8 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { } func updateThemeAndStrings(theme: PresentationTheme, strings: PresentationStrings) { + self.theme = theme + 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 +100,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 } @@ -99,7 +115,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { switch item { case .keyboard: return (PresentationResourcesChat.chatInputTextFieldKeyboardImage(theme), nil, strings.VoiceOver_Keyboard, 1.0, UIEdgeInsets()) - case let .stickers(enabled): + 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()) @@ -136,11 +152,48 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { } } - func updateLayout(size: CGSize) { - if let image = self.imageNode.image { + func updateLayout(item: ChatTextInputAccessoryItem, size: CGSize) { + self.item = item + + if let image = self.iconImageNode.image { 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 case let .stickers(_, isEmoji) = item, let animationView = self.animationView { + let animationFrame = imageFrame.insetBy(dx: -4.0, dy: -4.0) + + var colors: [String: UIColor] = [:] + let colorKeys: [String] = [ + "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" + ] + for colorKey in colorKeys { + colors[colorKey] = self.theme.chat.inputPanel.inputControlColor + } + let _ = animationView.update( + transition: .immediate, + component: AnyComponent(LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: !isEmoji ? "anim_stickertosmile" : "anim_smiletosticker", + colors: colors, + mode: .animateTransitionFromPrevious + ), + size: animationFrame.size + )), + environment: {}, + containerSize: animationFrame.size + ) + if let view = animationView.view { + if view.superview == nil { + self.view.addSubview(view) + } + view.frame = animationFrame + } + } } } @@ -196,7 +249,7 @@ private func calculateTextFieldRealInsets(presentationInterfaceState: ChatPresen } var right: CGFloat = 0.0 - right += accessoryButtonsWidth + right += max(0.0, accessoryButtonsWidth - 14.0) return UIEdgeInsets(top: 4.5 + top, left: 0.0, bottom: 5.5 + bottom, right: right) } @@ -347,13 +400,14 @@ 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 updateActivity: () -> Void = { } @@ -450,8 +504,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 } @@ -661,15 +716,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) } } } @@ -911,10 +966,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) + self.validLayout = (width, leftInset, rightInset, bottomInset, additionalSideInsets, maxHeight, metrics, isSecondary, isMediaInputExpanded) let textFieldWaitsForTouchUp: Bool if case .regular = metrics.widthClass, bottomInset.isZero { @@ -1228,8 +1282,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 } @@ -1661,7 +1716,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 { @@ -1784,9 +1839,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } var nextButtonTopRight = CGPoint(x: width - rightInset - textFieldInsets.right - accessoryButtonInset, y: panelHeight - textFieldInsets.bottom - minimalInputHeight) - for (_, button) in self.accessoryItemButtons.reversed() { + 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) @@ -2159,7 +2214,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 @@ -2299,8 +2354,10 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } } + let hideExpandMediaInput = hideMicButton + if mediaInputIsActive { - //hideMicButton = true + hideMicButton = true } if hideMicButton { @@ -2325,7 +2382,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } } - if mediaInputIsActive && !"".isEmpty { + if mediaInputIsActive && !hideExpandMediaInput { if self.actionButtons.expandMediaInputButton.alpha.isZero { self.actionButtons.expandMediaInputButton.alpha = 1.0 if animated { @@ -2350,7 +2407,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) { @@ -2836,7 +2893,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { } @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) @@ -2846,37 +2904,37 @@ 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 .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() } break } 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/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/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index e29d553d77..d1064dcaa8 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -379,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))) diff --git a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index 6d71ab7ba3..a99acd9b86 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -491,7 +491,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/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/TextFormat/Sources/StringWithAppliedEntities.swift b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift index 2d6ebff158..ad3588a8b4 100644 --- a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift +++ b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift @@ -249,6 +249,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), range: range) default: break } From e16bef63e732c0a3cc6ed55f2c4b30246db2f010 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 6 Jul 2022 13:00:49 +0200 Subject: [PATCH 032/113] Various improvements --- .../Sources/ViewControllerComponent.swift | 2 +- .../ContextControllerActionsStackNode.swift | 2 +- submodules/Emoji/Sources/EmojiUtils.swift | 2 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 103 +++++++++--------- .../Sources/PremiumIntroScreen.swift | 11 +- .../ChatMessageAnimatedStickerItemNode.swift | 3 +- .../WebUI/Sources/WebAppController.swift | 62 +++++++++++ 7 files changed, 127 insertions(+), 58 deletions(-) diff --git a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift index a0677bdd9e..b635d9e54f 100644 --- a/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift +++ b/submodules/Components/ViewControllerComponent/Sources/ViewControllerComponent.swift @@ -176,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/ContextUI/Sources/ContextControllerActionsStackNode.swift b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift index c69127b8c1..8989226abc 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 ) 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/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 2439774bcd..26d5e627a9 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -538,7 +538,6 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { let fade = Child(RoundedRectangle.self) let text = Child(MultilineTextComponent.self) let section = Child(ProductGroupComponent.self) - let termsText = Child(MultilineTextComponent.self) return { context in let sideInset: CGFloat = 16.0 @@ -687,55 +686,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { size.height += section.size.height size.height += 23.0 - let textSideInset: CGFloat = 16.0 - 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: strings.Premium_Gift_Info, - attributes: termsMarkdownAttributes - ) - - let accountContext = component.context - let peerId = component.peer.id - let present = component.present - - 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: .profile(peerId)) - 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: size.height + termsText.size.height / 2.0)) -// ) - context.add(termsText - .position(CGPoint(x: sideInset + environment.safeInsets.left + textSideInset + termsText.size.width / 2.0, y: size.height + 164.0 + termsText.size.height / 2.0)) - ) - size.height += termsText.size.height size.height += 10.0 size.height += scrollEnvironment.insets.bottom @@ -885,7 +836,6 @@ private final class PremiumGiftScreenComponent: CombinedComponent { strongSelf.updateInProgress(false) strongSelf.updated(transition: .immediate) -// strongSelf.completion(duration) addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail") @@ -958,6 +908,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { 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 @@ -1098,7 +1049,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { .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 @@ -1193,6 +1144,56 @@ private final class PremiumGiftScreenComponent: CombinedComponent { }) ) + 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 } } diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 0dcb18a9b6..44ff71410a 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -39,6 +39,7 @@ public enum PremiumSource: Equatable { case deeplink(String?) case profile(PeerId) case gift(from: PeerId, to: PeerId, duration: Int32) + case giftTerms var identifier: String? { switch self { @@ -74,7 +75,7 @@ public enum PremiumSource: Equatable { return "double_limits__about" case let .profile(id): return "profile__\(id.id._internalGetInt64Value())" - case .gift: + case .gift, .giftTerms: return nil case let .deeplink(reference): if let reference = reference { @@ -819,7 +820,9 @@ 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 @@ -1447,7 +1450,9 @@ private final class PremiumIntroScreenComponent: CombinedComponent { ) let titleString: String - if case .gift = context.component.source { + 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 diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 4bc9f720fa..e56e2408dc 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -1685,7 +1685,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) diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 216afd8217..dbf561cd29 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -723,6 +723,60 @@ 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 = { + self.sendAlertButtonEvent(id: nil) + } + self.controller?.present(alertController, in: .window(.root)) + } default: break } @@ -834,6 +888,14 @@ 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 = "{id: \"\(id)\"}" + } + self.webView?.sendEvent(name: "popup_closed", data: paramsString) + } } fileprivate var controllerNode: Node { From 0c2f2ec1b7d76af3d806d94d426ec25385d3a75a Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 6 Jul 2022 13:01:36 +0200 Subject: [PATCH 033/113] Update localization --- Telegram/Telegram-iOS/en.lproj/Localizable.strings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index f9142b2715..d682f4bf7d 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7834,3 +7834,6 @@ Sorry for the inconvenience."; "Notification.PremiumGift.Title" = "Telegram Premium"; "Notification.PremiumGift.Subtitle" = "for %@"; "Notification.PremiumGift.View" = "View"; + +"Gallery.AirPlay" = "AirPlay"; +"Gallery.AirPlayPlaceholder" = "This video is playing on the TV using AirPlay"; From d4f4e1076162b8f631d686e4d430b3d91ce60ff5 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 6 Jul 2022 14:25:24 +0200 Subject: [PATCH 034/113] Fix invoice image loading --- .../Sources/BotCheckoutHeaderItem.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutHeaderItem.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutHeaderItem.swift index 38bbe6315c..48847922ce 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutHeaderItem.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutHeaderItem.swift @@ -8,6 +8,7 @@ import TelegramPresentationData import ItemListUI import PresentationDataUtils import PhotoResources +import Postbox class BotCheckoutHeaderItem: ListViewItem, ItemListItem { let account: Account @@ -77,6 +78,8 @@ class BotCheckoutHeaderItemNode: ListViewItemNode { private var item: BotCheckoutHeaderItem? + private let fetchDisposable = MetaDisposable() + init() { self.backgroundNode = ASDisplayNode() self.backgroundNode.isLayerBacked = true @@ -119,6 +122,10 @@ class BotCheckoutHeaderItemNode: ListViewItemNode { self.addSubnode(self.botNameNode) } + deinit { + self.fetchDisposable.dispose() + } + func asyncLayout() -> (_ item: BotCheckoutHeaderItem, _ params: ListViewItemLayoutParams, _ neighbors: ItemListNeighbors) -> (ListViewItemNodeLayout, () -> Void) { let makeTitleLayout = TextNode.asyncLayout(self.titleNode) let makeTextLayout = TextNode.asyncLayout(self.textNode) @@ -159,12 +166,14 @@ class BotCheckoutHeaderItemNode: ListViewItemNode { var imageApply: (() -> Void)? var updatedImageSignal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>? + var updatedFetchSignal: Signal? if let photo = item.invoice.photo, let dimensions = photo.dimensions { let arguments = TransformImageArguments(corners: ImageCorners(radius: 4.0), imageSize: dimensions.cgSize.aspectFilled(imageSize), boundingSize: imageSize, intrinsicInsets: UIEdgeInsets(), emptyColor: item.theme.list.mediaPlaceholderColor) imageApply = makeImageLayout(arguments) maxTextWidth = max(1.0, maxTextWidth - imageSize.width - imageTextSpacing) if imageUpdated { updatedImageSignal = chatWebFileImage(account: item.account, file: photo) + updatedFetchSignal = fetchedMediaResource(mediaBox: item.account.postbox.mediaBox, reference: .standalone(resource: photo.resource)) } } @@ -206,6 +215,9 @@ class BotCheckoutHeaderItemNode: ListViewItemNode { if let updatedImageSignal = updatedImageSignal { strongSelf.imageNode.setSignal(updatedImageSignal) } + if let updatedFetchSignal = updatedFetchSignal { + strongSelf.fetchDisposable.set(updatedFetchSignal.start()) + } strongSelf.imageNode.isHidden = false } else { strongSelf.imageNode.isHidden = true From 2377d3e08c581e0cf0c98b7697a19bb3e788b772 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 6 Jul 2022 14:25:48 +0200 Subject: [PATCH 035/113] Fix button interactions --- submodules/ComponentFlow/Source/Host/ComponentHostView.swift | 5 ++++- .../Sources/AudioTranscriptionButtonComponent.swift | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift index 0e27198b92..e5407341f4 100644 --- a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift +++ b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift @@ -109,8 +109,11 @@ public final class ComponentHostView: UIView { if self.alpha.isZero { return nil } + if !self.isUserInteractionEnabled { + return nil + } for view in self.subviews.reversed() { - if let result = view.hitTest(self.convert(point, to: view), with: event), result.isUserInteractionEnabled { + if view.isUserInteractionEnabled, view.alpha != 0.0, let result = view.hitTest(self.convert(point, to: view), with: event) { return result } } diff --git a/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift b/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift index 800d67a95d..9965a8ca92 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) From 9d41d0f110ce11dc79f355b5a4557c50d9289bb6 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 8 Jul 2022 14:30:49 +0200 Subject: [PATCH 036/113] Various improvements --- Telegram/Telegram-iOS/Resources/Gift.tgs | Bin 0 -> 53808 bytes .../Telegram-iOS/en.lproj/Localizable.strings | 3 + .../Items/UniversalVideoGalleryItem.swift | 186 ++++++++++------- .../PremiumUI/Sources/PremiumGiftScreen.swift | 21 +- .../Sources/PremiumIntroScreen.swift | 12 +- .../Components/MediaStreamComponent.swift | 27 ++- .../Components/Gift.imageset/Contents.json | 21 -- .../Components/Gift.imageset/gift.png | Bin 47754 -> 0 bytes .../AirPlay.imageset/Airplay.pdf | 188 ++++++++++++++++++ .../AirPlay.imageset/Contents.json | 12 ++ .../Sources/ChatMessageGiftItemNode.swift | 38 ++-- .../Sources/ExternalVideoPlayer.swift | 121 +++++++++++ .../WebUI/Sources/WebAppController.swift | 4 + 13 files changed, 510 insertions(+), 123 deletions(-) create mode 100644 Telegram/Telegram-iOS/Resources/Gift.tgs delete mode 100644 submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/Contents.json delete mode 100644 submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/gift.png create mode 100644 submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Airplay.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Media Gallery/AirPlay.imageset/Contents.json create mode 100644 submodules/TelegramUniversalVideoContent/Sources/ExternalVideoPlayer.swift diff --git a/Telegram/Telegram-iOS/Resources/Gift.tgs b/Telegram/Telegram-iOS/Resources/Gift.tgs new file mode 100644 index 0000000000000000000000000000000000000000..f0b6f7a3cb65ff72f3ffa346b15a77aacb43d5a9 GIT binary patch literal 53808 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 N{(sqI(4N)r1OV0nlJ5Wj literal 0 HcmV?d00001 diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index d682f4bf7d..3c0613cc7c 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7831,6 +7831,9 @@ Sorry for the inconvenience."; "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"; diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index dba478408d..f0d487f5cd 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() } } @@ -2457,6 +2477,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 { if let webpage = media as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content { @@ -2578,63 +2608,85 @@ 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 - - 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() - } - } - 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 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)) - } - }, dismissed: { [weak self] in - self?.isInteractingPromise.set(false) - }) - (baseNavigationController?.topViewController as? ViewController)?.present(controller, in: .window(.root), with: nil) - }) + 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() + } + } + } + |> 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 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)) + } + }, 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/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 26d5e627a9..a1188dd1ef 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -799,11 +799,11 @@ private final class PremiumGiftScreenComponent: CombinedComponent { let duration: Int32 switch product.id { case "org.telegram.telegramPremium.twelveMonths": - duration = 86400 * 365 + duration = 12 case "org.telegram.telegramPremium.sixMonths": - duration = 86400 * 180 + duration = 6 case "org.telegram.telegramPremium.threeMonths": - duration = 86400 * 90 + duration = 3 default: duration = 0 } @@ -1259,13 +1259,16 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { } completionImpl = { [weak self] duration in - if let strongSelf = self { - let navigationController = strongSelf.navigationController - strongSelf.dismiss() - let introController = PremiumIntroScreen(context: context, source: .gift(from: context.account.peerId, to: peerId, duration: duration)) - navigationController?.pushViewController(introController, animated: true) + if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { +// let introController = PremiumIntroScreen(context: context, source: .gift(from: context.account.peerId, to: peerId, duration: duration)) + var controllers = navigationController.viewControllers + controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) } + navigationController.setViewControllers(controllers, animated: true) + Queue.mainQueue().after(0.1, { - introController.view.addSubview(ConfettiView(frame: introController.view.bounds)) + if let topController = navigationController.viewControllers.first { + topController.view.addSubview(ConfettiView(frame: topController.view.bounds)) + } }) } } diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 44ff71410a..1d38ee523a 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -1487,21 +1487,21 @@ private final class PremiumIntroScreenComponent: CombinedComponent { 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 >= 86400 * 365 { + if duration == 12 { secondaryTitleText = environment.strings.Premium_GiftedTitleYou_12Month(otherPeerName).string - } else if duration >= 86400 * 180 { + } else if duration == 6 { secondaryTitleText = environment.strings.Premium_GiftedTitleYou_6Month(otherPeerName).string - } else if duration >= 86400 * 90 { + } else if duration == 3 { secondaryTitleText = environment.strings.Premium_GiftedTitleYou_3Month(otherPeerName).string } else { secondaryTitleText = "" } } else { - if duration >= 86400 * 365 { + if duration == 12 { secondaryTitleText = environment.strings.Premium_GiftedTitle_12Month(otherPeerName).string - } else if duration >= 86400 * 180 { + } else if duration == 6 { secondaryTitleText = environment.strings.Premium_GiftedTitle_6Month(otherPeerName).string - } else if duration >= 86400 * 90 { + } else if duration == 3 { secondaryTitleText = environment.strings.Premium_GiftedTitle_3Month(otherPeerName).string } else { secondaryTitleText = "" diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index 930de2caa4..e9992927ac 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -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: 353.0, 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: 353.0, 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/TelegramUI/Images.xcassets/Components/Gift.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/Contents.json deleted file mode 100644 index 74c463b66f..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/Contents.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "gift.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/gift.png b/submodules/TelegramUI/Images.xcassets/Components/Gift.imageset/gift.png deleted file mode 100644 index a31babda90031ee20a4069c04bdafb257dd25042..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47754 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 +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/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift index db3f927777..c498faa0cc 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -14,6 +14,8 @@ 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) @@ -29,8 +31,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { private let mediaBackgroundNode: NavigationBackgroundNode private let titleNode: TextNode private let subtitleNode: TextNode - - private let giftNode: ASImageNode + private let animationNode: AnimatedStickerNode private let buttonNode: HighlightTrackingButtonNode private let buttonStarsNode: PremiumStarsNode @@ -62,10 +63,10 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { self.buttonNode = HighlightTrackingButtonNode() self.buttonNode.clipsToBounds = true self.buttonNode.cornerRadius = 17.0 - - self.giftNode = ASImageNode() - self.giftNode.isUserInteractionEnabled = false - self.giftNode.displaysAsynchronously = false + + self.animationNode = DefaultAnimatedStickerNodeImpl() + self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Gift"), width: 384, height: 384, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + self.animationNode.visibility = true self.buttonStarsNode = PremiumStarsNode() @@ -80,7 +81,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { self.addSubnode(self.mediaBackgroundNode) self.addSubnode(self.titleNode) self.addSubnode(self.subtitleNode) - self.addSubnode(self.giftNode) + self.addSubnode(self.animationNode) self.addSubnode(self.buttonNode) self.buttonNode.addSubnode(self.buttonStarsNode) @@ -128,7 +129,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { let contentProperties = ChatMessageBubbleContentProperties(hidesSimpleAuthorHeader: true, headerSpacing: 0.0, hidesBackground: .always, forceFullCorners: false, forceAlignment: .center) return (contentProperties, nil, CGFloat.greatestFiniteMagnitude, { constrainedSize, position in - let imageSize = CGSize(width: 220.0, height: 210.0) + 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) @@ -139,7 +140,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { if let action = media as? TelegramMediaAction { switch action.action { case let .giftPremium(_, _, durationValue): - duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(timeIntervalString(strings: item.presentationData.strings, value: durationValue)).string + duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(item.presentationData.strings.Notification_PremiumGift_Months(durationValue)).string default: break } @@ -148,11 +149,11 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { 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: imageSize.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: imageSize.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: imageSize.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 { @@ -184,7 +185,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { backgroundMaskUpdated = true } - let backgroundSize = CGSize(width: labelLayout.size.width + 8.0 + 8.0, height: labelLayout.size.height + imageSize.height + 18.0) + 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 @@ -193,7 +194,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) - let imageFrame = CGRect(origin: CGPoint(x: floorToScreenPixels((backgroundSize.width - imageSize.width) / 2.0), y: labelLayout.size.height + 16.0), size: imageSize) + 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 @@ -201,10 +202,9 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { 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) - strongSelf.giftNode.image = UIImage(bundleImageName: "Components/Gift") - if let image = strongSelf.giftNode.image { - strongSelf.giftNode.frame = CGRect(origin: CGPoint(x: mediaBackgroundFrame.minX + floorToScreenPixels((mediaBackgroundFrame.width - image.size.width) / 2.0), y: mediaBackgroundFrame.minY + 14.0), size: image.size) - } + 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() @@ -214,7 +214,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { 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 + 121.0), size: titleLayout.size) + 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) 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/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index dbf561cd29..e75e08da6c 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -777,6 +777,10 @@ public final class WebAppController: ViewController, AttachmentContainable { } self.controller?.present(alertController, in: .window(.root)) } + case "web_app_setup_closing_behavior": + if let json = json, let _ = json["need_confirmation"] as? String { + + } default: break } From 1ac654e8b213c285dd7fae1dbfa5ba9822454fa4 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 8 Jul 2022 15:09:55 +0200 Subject: [PATCH 037/113] [Temp] custom emoji layouts --- .../Source/Base/Transition.swift | 50 +- .../Display/Source/ImmediateTextNode.swift | 8 +- submodules/Display/Source/TextNode.swift | 42 +- .../Sources/StatsMessageItem.swift | 2 +- .../Sources/MessageContentKind.swift | 89 +++- submodules/TelegramUI/BUILD | 1 + .../Sources/EmojiTextAttachmentView.swift | 6 +- .../Sources/EntityKeyboard.swift | 92 +++- .../EntityKeyboardTopPanelComponent.swift | 14 +- .../Sources/GifPagerContentComponent.swift | 19 +- .../Components/TextNodeWithEntities/BUILD | 24 + .../Sources/TextNodeWithEntities.swift | 466 ++++++++++++++++++ .../Sources/ChatControllerNode.swift | 6 +- .../Sources/ChatEntityKeyboardInputNode.swift | 174 ++++++- .../ChatInterfaceStateAccessoryPanels.swift | 4 +- .../ChatMessageAnimatedStickerItemNode.swift | 12 +- .../Sources/ChatMessageBubbleItemNode.swift | 26 +- .../ChatMessageInstantVideoItemNode.swift | 12 +- .../Sources/ChatMessageNotificationItem.swift | 4 +- .../Sources/ChatMessageReplyInfoNode.swift | 150 ++++-- .../Sources/ChatMessageStickerItemNode.swift | 12 +- .../ChatMessageTextBubbleContentNode.swift | 185 ++----- .../ChatPinnedMessageTitlePanelNode.swift | 4 +- .../Sources/EditAccessoryPanelNode.swift | 3 +- .../Sources/ReplyAccessoryPanelNode.swift | 27 +- .../WebpagePreviewAccessoryPanelNode.swift | 6 +- 26 files changed, 1155 insertions(+), 283 deletions(-) create mode 100644 submodules/TelegramUI/Components/TextNodeWithEntities/BUILD create mode 100644 submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index a44933d09d..363a67f497 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -202,20 +202,26 @@ public struct Transition { } switch self.animation { case .none: - view.bounds = CGRect(origin: view.bounds.origin, size: frame.size) - view.layer.position = CGPoint(x: frame.midX, y: frame.midY) + 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.layer.presentation()?.position ?? view.center - let previousBounds = view.layer.presentation()?.bounds ?? 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.bounds = CGRect(origin: previousBounds.origin, size: frame.size) - view.center = CGPoint(x: frame.midX, y: frame.midY) + 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)) } } @@ -230,7 +236,12 @@ public struct Transition { view.layer.removeAnimation(forKey: "bounds") completion?(true) case .curve: - let previousBounds = view.layer.presentation()?.bounds ?? 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) @@ -248,7 +259,12 @@ public struct Transition { view.layer.removeAnimation(forKey: "position") completion?(true) case .curve: - let previousPosition = view.layer.presentation()?.position ?? 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) @@ -266,7 +282,12 @@ public struct Transition { layer.removeAnimation(forKey: "bounds") completion?(true) case .curve: - let previousBounds = layer.presentation()?.bounds ?? layer.bounds + 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) @@ -284,7 +305,12 @@ public struct Transition { layer.removeAnimation(forKey: "position") completion?(true) case .curve: - let previousPosition = layer.presentation()?.position ?? layer.position + 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) 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/TextNode.swift b/submodules/Display/Source/TextNode.swift index 9bc8efeef9..8231bad342 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -148,7 +148,23 @@ public final class TextNodeLayoutArguments { public let textStroke: (UIColor, CGFloat)? public let displaySpoilers: 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 + ) { self.attributedString = attributedString self.backgroundColor = backgroundColor self.minimumNumberOfLines = minimumNumberOfLines @@ -165,6 +181,26 @@ public final class TextNodeLayoutArguments { self.textStroke = textStroke self.displaySpoilers = displaySpoilers } + + 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 + ) + } } public final class TextNodeLayout: NSObject { @@ -881,7 +917,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 +928,7 @@ public class TextNode: ASDisplayNode { self.clipsToBounds = false } - override public func didLoad() { + override open func didLoad() { super.didLoad() } 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/TelegramStringFormatting/Sources/MessageContentKind.swift b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift index cc00c25f01..49fd545979 100644 --- a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift +++ b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift @@ -3,6 +3,7 @@ import TelegramCore import TelegramPresentationData import TelegramUIPreferences import PlatformRestrictionMatching +import TextFormat public enum MessageContentKindKey { case text @@ -26,7 +27,7 @@ public enum MessageContentKindKey { } public enum MessageContentKind: Equatable { - case text(String) + case text(NSAttributedString) case image case video case videoMessage @@ -87,6 +88,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) + + 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 +136,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 +205,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 +224,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 +298,10 @@ public func foldLineBreaks(_ text: String) -> String { return result } +public func foldLineBreaks(_ text: NSAttributedString) -> NSAttributedString { + //TODO:localize + return text +} public func trimToLineCount(_ text: String, lineCount: Int) -> String { if lineCount < 1 { diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index 7fe179a22d..4d9a0a1245 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -288,6 +288,7 @@ swift_library( "//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", diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index eecc39922f..630b33ea0e 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -54,7 +54,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } } - public init(context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { + public init(context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) { self.context = context self.groupId = groupId self.emoji = emoji @@ -63,7 +63,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { self.placeholderColor = placeholderColor let scale = min(2.0, UIScreenScale) - self.pointSize = CGSize(width: 24, height: 24) + self.pointSize = pointSize self.pixelSize = CGSize(width: self.pointSize.width * scale, height: self.pointSize.height * scale) super.init() @@ -180,7 +180,7 @@ public final class EmojiTextAttachmentView: UIView { private let contentLayer: InlineStickerItemLayer public init(context: AccountContext, emoji: ChatTextInputTextCustomEmojiAttribute, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { - self.contentLayer = InlineStickerItemLayer(context: context, groupId: "textInputView", attemptSynchronousLoad: true, emoji: emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor) + self.contentLayer = InlineStickerItemLayer(context: context, groupId: "textInputView", attemptSynchronousLoad: true, emoji: emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: 24.0, height: 24.0)) super.init(frame: CGRect()) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 12cba3bc97..27c9e26502 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -41,16 +41,43 @@ public final class EntityKeyboardComponent: Component { } } + 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 bottomInset: CGFloat public let emojiContent: EmojiPagerContentComponent public let stickerContent: EmojiPagerContentComponent public let gifContent: GifPagerContentComponent + 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 @@ -62,11 +89,13 @@ public final class EntityKeyboardComponent: Component { emojiContent: EmojiPagerContentComponent, stickerContent: EmojiPagerContentComponent, gifContent: GifPagerContentComponent, + 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, @@ -77,11 +106,13 @@ public final class EntityKeyboardComponent: Component { self.emojiContent = emojiContent self.stickerContent = stickerContent self.gifContent = gifContent + 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 @@ -104,6 +135,9 @@ public final class EntityKeyboardComponent: Component { if lhs.gifContent != rhs.gifContent { return false } + if lhs.availableGifSearchEmojies != rhs.availableGifSearchEmojies { + return false + } if lhs.defaultToEmojiTab != rhs.defaultToEmojiTab { return false } @@ -162,26 +196,58 @@ public final class EntityKeyboardComponent: Component { let gifsContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(component.gifContent))) var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] - topGifItems.removeAll() - /*topGifItems.append(EntityKeyboardTopPanelComponent.Item( + //TODO:localize + topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: "recent", - content: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/RecentTabIcon", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: CGSize(width: 30.0, height: 30.0)) - ) + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: "Chat/Input/Media/RecentTabIcon", + theme: component.theme, + title: "Recent", + pressed: { [weak self] in + self?.component?.switchToGifSubject(.recent) + } + )) )) topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: "trending", - content: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/TrendingGifs", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: CGSize(width: 30.0, height: 30.0)) - ) - ))*/ + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: "Chat/Input/Media/TrendingGifs", + theme: component.theme, + title: "Trending", + pressed: { [weak self] in + self?.component?.switchToGifSubject(.trending) + } + )) + )) + for emoji in component.availableGifSearchEmojies { + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: emoji.emoji, + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.stickerContent.context, + file: emoji.file, + animationCache: component.stickerContent.animationCache, + animationRenderer: component.stickerContent.animationRenderer, + theme: component.theme, + title: emoji.title, + pressed: { [weak self] in + self?.component?.switchToGifSubject(.emojiSearch(emoji.emoji)) + } + )) + )) + } + let defaultActiveGifItemId: AnyHashable + switch component.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, + defaultActiveItemId: defaultActiveGifItemId, activeContentItemIdUpdated: gifsContentItemIdUpdated )))) contentIcons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(BundleIconComponent( diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index daf3de90ef..6a685fcf26 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -364,15 +364,18 @@ final class EntityKeyboardTopPanelComponent: Component { let theme: PresentationTheme let items: [Item] + let defaultActiveItemId: AnyHashable? let activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)> init( theme: PresentationTheme, items: [Item], + defaultActiveItemId: AnyHashable? = nil, activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)> ) { self.theme = theme self.items = items + self.defaultActiveItemId = defaultActiveItemId self.activeContentItemIdUpdated = activeContentItemIdUpdated } @@ -383,6 +386,9 @@ final class EntityKeyboardTopPanelComponent: Component { if lhs.items != rhs.items { return false } + if lhs.defaultActiveItemId != rhs.defaultActiveItemId { + return false + } if lhs.activeContentItemIdUpdated !== rhs.activeContentItemIdUpdated { return false } @@ -613,6 +619,10 @@ final class EntityKeyboardTopPanelComponent: Component { } self.component = component + if let defaultActiveItemId = component.defaultActiveItemId { + self.activeContentItemId = defaultActiveItemId + } + let panelEnvironment = environment[EntityKeyboardTopContainerPanelEnvironment.self].value self.environment = panelEnvironment @@ -639,8 +649,8 @@ final class EntityKeyboardTopPanelComponent: Component { let previousItemFrame = previousItemLayout.containerFrame(at: previousVisibleRange.minIndex) let updatedItemFrame = itemLayout.containerFrame(at: previousVisibleRange.minIndex) - let previousDistanceToItemFraction = (previousItemFrame.minX - self.scrollView.bounds.minX) / previousItemFrame.width - let newBounds = CGRect(origin: CGPoint(x: updatedItemFrame.minX - floor(previousDistanceToItemFraction * updatedItemFrame.width), y: 0.0), size: availableSize) + let previousDistanceToItem = (previousItemFrame.minX - self.scrollView.bounds.minX)// / previousItemFrame.width + let newBounds = CGRect(origin: CGPoint(x: updatedItemFrame.minX - previousDistanceToItem/* * updatedItemFrame.width)*/, y: 0.0), size: availableSize) updatedBounds = newBounds var updatedVisibleBounds = newBounds diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index 02936915b6..c57bb93a13 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -117,6 +117,12 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer { 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 @@ -148,15 +154,18 @@ public final class GifPagerContentComponent: Component { public let context: AccountContext public let inputInteraction: InputInteraction + public let subject: Subject public let items: [Item] public init( context: AccountContext, inputInteraction: InputInteraction, + subject: Subject, items: [Item] ) { self.context = context self.inputInteraction = inputInteraction + self.subject = subject self.items = items } @@ -167,6 +176,9 @@ public final class GifPagerContentComponent: Component { if lhs.inputInteraction !== rhs.inputInteraction { return false } + if lhs.subject != rhs.subject { + return false + } if lhs.items != rhs.items { return false } @@ -363,7 +375,10 @@ public final class GifPagerContentComponent: Component { } } - private let scrollView: UIScrollView + private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { + } + + private let scrollView: ContentScrollView private var visibleItemLayers: [MediaId: ItemLayer] = [:] private var ignoreScrolling: Bool = false @@ -374,7 +389,7 @@ public final class GifPagerContentComponent: Component { private var itemLayout: ItemLayout? override init(frame: CGRect) { - self.scrollView = UIScrollView() + self.scrollView = ContentScrollView() super.init(frame: frame) 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..f45bd8eed8 --- /dev/null +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -0,0 +1,466 @@ +import Foundation +import UIKit +import Display +import AsyncDisplayKit +import EmojiTextAttachmentView +import TextFormat +import AccountContext +import AnimationCache +import MultiAnimationRenderer + +private final class InlineStickerItem: Hashable { + let emoji: ChatTextInputTextCustomEmojiAttribute + let fontSize: CGFloat + + init(emoji: ChatTextInputTextCustomEmojiAttribute, fontSize: CGFloat) { + self.emoji = emoji + 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.fontSize != rhs.fontSize { + return false + } + return true + } +} + +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 init( + context: AccountContext, + cache: AnimationCache, + renderer: MultiAnimationRenderer, + placeholderColor: UIColor + ) { + self.context = context + self.cache = cache + self.renderer = renderer + self.placeholderColor = placeholderColor + } + } + + 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) + + 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: ChatTextInputTextCustomEmojiAttribute(stickerPack: value.stickerPack, fileId: value.fileId), fontSize: font.pointSize), range: range) + } + } + }) + + 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) + } + + 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) + } + + 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) { + 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 { + itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + 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: ChatTextInputTextCustomEmojiAttribute(stickerPack: value.stickerPack, fileId: value.fileId), 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 { + itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + 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/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 34a5d34f2a..db2c38c78f 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -918,7 +918,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 @@ -1113,7 +1113,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var accessoryPanelSize: CGSize? var immediatelyLayoutAccessoryPanelAndAnimateAppearance = false - if let accessoryPanelNode = accessoryPanelForChatPresentationIntefaceState(self.chatPresentationInterfaceState, context: self.context, currentPanel: self.accessoryPanelNode, interfaceInteraction: self.interfaceInteraction) { + 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) @@ -2679,7 +2679,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) { diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index f5a5170437..9ea40f893a 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -18,18 +18,21 @@ import PagerComponent final class ChatEntityKeyboardInputNode: ChatInputNode { struct InputData: Equatable { - let emoji: EmojiPagerContentComponent - let stickers: EmojiPagerContentComponent - let gifs: GifPagerContentComponent + var emoji: EmojiPagerContentComponent + var stickers: EmojiPagerContentComponent + var gifs: GifPagerContentComponent + var availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] init( emoji: EmojiPagerContentComponent, stickers: EmojiPagerContentComponent, - gifs: GifPagerContentComponent + gifs: GifPagerContentComponent, + availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] ) { self.emoji = emoji self.stickers = stickers self.gifs = gifs + self.availableGifSearchEmojies = availableGifSearchEmojies } } @@ -419,7 +422,39 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { ) } - let gifItems: Signal = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + 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 + } + + // We are intentionally not subscribing to the recent gif updates here + let gifItems: Signal = context.engine.data.get(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) |> map { savedGifs -> GifPagerContentComponent in var items: [GifPagerContentComponent.Item] = [] for gifItem in savedGifs { @@ -430,6 +465,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return GifPagerContentComponent( context: context, inputInteraction: gifInputInteraction, + subject: .recent, items: items ) } @@ -437,13 +473,23 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return combineLatest(queue: .mainQueue(), emojiItems, stickerItems, - gifItems + gifItems, + reactions, + animatedEmojiStickers ) - |> map { emoji, stickers, gifs -> InputData in + |> map { emoji, stickers, gifs, reactions, animatedEmojiStickers -> InputData in + var availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] = [] + for reaction in reactions { + if let file = animatedEmojiStickers[reaction]?.first?.file { + availableGifSearchEmojies.append(EntityKeyboardComponent.GifSearchEmoji(emoji: reaction, file: file, title: reaction)) + } + } + return InputData( emoji: emoji, stickers: stickers, - gifs: gifs + gifs: gifs, + availableGifSearchEmojies: availableGifSearchEmojies ) } } @@ -470,6 +516,13 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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 gifMode: GifPagerContentComponent.Subject = .recent { + didSet { + self.gifModeSubject.set(self.gifMode) + } + } + private let gifModeSubject: ValuePromise + init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction) { self.context = context self.currentInputData = currentInputData @@ -479,17 +532,25 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.entityKeyboardView = ComponentHostView() + self.gifModeSubject = ValuePromise(self.gifMode, ignoreRepeated: true) + super.init() self.view.addSubview(self.entityKeyboardView) self.externalTopPanelContainerImpl = PagerExternalTopPanelContainer() - self.inputDataDisposable = (updatedInputData - |> deliverOnMainQueue).start(next: { [weak self] inputData in + self.inputDataDisposable = (combineLatest(queue: .mainQueue(), + updatedInputData, + self.updatedGifs() + ) + |> deliverOnMainQueue).start(next: { [weak self] inputData, gifs in guard let strongSelf = self else { return } + var inputData = inputData + inputData.gifs = gifs + strongSelf.currentInputData = inputData strongSelf.performLayout() }) @@ -531,6 +592,92 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.inputDataDisposable?.dispose() } + private func updatedGifs() -> Signal { + let gifInputInteraction = GifPagerContentComponent.InputInteraction( + performItemAction: { [weak controllerInteraction] item, view, rect in + guard let controllerInteraction = controllerInteraction else { + return + } + let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) + } + ) + + let context = self.context + let trendingGifs = self.trendingGifsPromise.get() + let updatedGifs = self.gifModeSubject.get() + |> mapToSignal { subject -> Signal in + switch subject { + case .recent: + let gifItems: Signal = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + |> map { savedGifs -> GifPagerContentComponent in + var items: [GifPagerContentComponent.Item] = [] + for gifItem in savedGifs { + items.append(GifPagerContentComponent.Item( + file: gifItem.contents.get(RecentMediaItem.self)!.media + )) + } + return GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items + ) + } + return gifItems + case .trending: + return trendingGifs + |> map { trendingGifs -> GifPagerContentComponent in + var items: [GifPagerContentComponent.Item] = [] + + if let trendingGifs = trendingGifs { + for file in trendingGifs.files { + items.append(GifPagerContentComponent.Item( + file: file.file.media + )) + } + } + + return GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items + ) + } + case let .emojiSearch(query): + return paneGifSearchForQuery(context: context, query: query, offset: nil, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil) + |> map { result -> GifPagerContentComponent in + var items: [GifPagerContentComponent.Item] = [] + + /*let canLoadMore: Bool + if let result = result { + canLoadMore = !result.isComplete + } else { + canLoadMore = true + }*/ + + if let result = result { + for file in result.files { + items.append(GifPagerContentComponent.Item( + file: file.file.media + )) + } + } + + return GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items + ) + } + } + } + + return .single(self.currentInputData.gifs) + |> then(updatedGifs) + } + func markInputCollapsed() { self.isMarkInputCollapsed = true } @@ -574,6 +721,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { emojiContent: self.currentInputData.emoji, stickerContent: self.currentInputData.stickers, gifContent: self.currentInputData.gifs, + availableGifSearchEmojies: self.currentInputData.availableGifSearchEmojies, defaultToEmojiTab: self.defaultToEmojiTab, externalTopPanelContainer: self.externalTopPanelContainerImpl, topPanelExtensionUpdated: { [weak self] topPanelExtension, transition in @@ -603,6 +751,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return .text } }, + switchToGifSubject: { [weak self] subject in + guard let strongSelf = self else { + return + } + strongSelf.gifModeSubject.set(subject) + }, makeSearchContainerNode: { content in let mappedMode: ChatMediaInputSearchMode switch content { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift index 54f4784e65..f56092af6e 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 } @@ -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/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 4bc9f720fa..cf292275b6 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -1017,7 +1017,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 diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 36ba7e2138..20e0337914 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -530,13 +530,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 + } } } } @@ -1039,7 +1035,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, () -> 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)), @@ -1802,7 +1798,17 @@ 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)) + 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, { sizeAndApply.1() }) replyInfoOriginY = headerSize.height @@ -2489,6 +2495,8 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode 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/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index 6fc9c5eddb..1034a9c0a5 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -458,7 +458,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 { diff --git a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift index 23ef6310c4..d61ba7bd2a 100644 --- a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift @@ -196,10 +196,10 @@ final class ChatMessageNotificationItemNode: NotificationItemNode { } 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 diff --git a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift index 0f6935d5ba..6eabcd003c 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, () -> 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) } 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,12 +255,12 @@ 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) } } } @@ -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) + } + 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/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 2f57d3b0a4..941f83c408 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -570,7 +570,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 diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index b5c56c774e..d6a2bb8278 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,27 +47,8 @@ private final class CachedChatMessageText { } } -private final class InlineStickerItem: Hashable { - let emoji: ChatTextInputTextCustomEmojiAttribute - - init(emoji: ChatTextInputTextCustomEmojiAttribute) { - self.emoji = emoji - } - - func hash(into hasher: inout Hasher) { - hasher.combine(emoji.fileId) - } - - static func ==(lhs: InlineStickerItem, rhs: InlineStickerItem) -> Bool { - if lhs.emoji.fileId != rhs.emoji.fileId { - return false - } - return true - } -} - class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { - private let textNode: TextNode + private let textNode: TextNodeWithEntities private var spoilerTextNode: TextNode? private var dustNode: InvisibleInkDustNode? @@ -76,42 +58,27 @@ 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 + case let .visible(_, subRect): + var subRect = subRect + subRect.origin.x = 0.0 + subRect.size.width = 10000.0 + self.textNode.visibilityRect = subRect } } } } required init() { - self.textNode = TextNode() + self.textNode = TextNodeWithEntities() self.statusNode = ChatMessageDateAndStatusNode() @@ -119,11 +86,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,7 +119,7 @@ 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 textLayout = TextNodeWithEntities.asyncLayout(self.textNode) let spoilerTextLayout = TextNode.asyncLayout(self.spoilerTextNode) let statusLayout = self.statusNode.asyncLayout() @@ -354,7 +321,6 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { 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(emoji: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId)) updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId) let insertString = NSAttributedString(string: updatedString.attributedSubstring(from: range).string, attributes: updatedAttributes) @@ -445,29 +411,29 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { 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)) + animation.animator.updateFrame(layer: strongSelf.textNode.textNode.layer, frame: textFrame, completion: nil) if let (_, spoilerTextApply) = spoilerTextLayoutAndApply { let spoilerTextNode = spoilerTextApply() @@ -514,8 +480,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) @@ -546,73 +511,29 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } - 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 itemLayer: InlineStickerItemLayer - if let current = self.inlineStickerItemLayers[id] { - itemLayer = current - } else { - itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, 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) @@ -669,8 +590,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, @@ -682,12 +603,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) } } } @@ -701,9 +622,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 @@ -716,16 +637,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)) @@ -742,7 +663,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 = [] } @@ -754,9 +675,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() { @@ -791,7 +712,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) @@ -802,7 +723,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) @@ -813,9 +734,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 { @@ -851,14 +772,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/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index f3843008d4..10382a35e1 100644 --- a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift @@ -650,10 +650,10 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { 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) } 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) diff --git a/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift index ff30790408..70af8117f2 100644 --- a/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift @@ -170,7 +170,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? diff --git a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift index b1fc27e49a..54b0552aee 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,11 +66,20 @@ 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) + if let animationCache = animationCache, let animationRenderer = animationRenderer { + self.textNode.arguments = TextNodeWithEntities.Arguments( + context: context, + cache: animationCache, + renderer: animationRenderer, + placeholderColor: theme.list.mediaPlaceholderColor + ) + } + self.imageNode = TransformImageNode() self.imageNode.contentAnimations = [.subsequentUpdates] self.imageNode.isHidden = true @@ -119,7 +131,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,9 +142,10 @@ 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 } } 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 } } From ed59ead31e1d5a85c5674cfe647256ea1e5346f7 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 8 Jul 2022 19:53:20 +0200 Subject: [PATCH 038/113] [WIP] Animated emoji --- .../Sources/ChatController.swift | 8 +- submodules/ChatListUI/BUILD | 3 + .../Sources/ChatListControllerNode.swift | 5 +- .../Sources/ChatListSearchContainerNode.swift | 2 +- .../Sources/ChatListSearchListPaneNode.swift | 19 +- .../Sources/Node/ChatListItem.swift | 66 ++++--- .../Sources/Node/ChatListNode.swift | 15 +- .../Sources/Node/ChatListNodeEntries.swift | 6 +- .../Sources/DebugController.swift | 16 +- .../ChatItemGalleryFooterContentNode.swift | 2 +- .../GalleryUI/Sources/GalleryController.swift | 8 +- .../SecretMediaPreviewController.swift | 2 +- .../Sources/HashtagSearchController.swift | 2 +- .../ImportStickerPackControllerNode.swift | 2 +- .../Sources/InstantPageControllerNode.swift | 2 +- .../Sources/ItemListAddressItem.swift | 2 +- .../Items/ItemListMultilineTextItem.swift | 2 +- .../Items/ItemListTextWithLabelItem.swift | 2 +- .../Sources/LegacyMediaPickers.swift | 14 +- .../Sources/MediaPickerSelectedListNode.swift | 4 +- .../Pasteboard/Sources/Pasteboard.swift | 22 ++- .../Postbox/Sources/ChatListViewState.swift | 2 +- .../Sources/GlobalMessageTagsView.swift | 2 +- submodules/Postbox/Sources/Media.swift | 4 - submodules/Postbox/Sources/Message.swift | 29 +-- .../Postbox/Sources/MessageHistoryTable.swift | 22 ++- .../Postbox/Sources/MessageHistoryView.swift | 2 +- .../Sources/MessageHistoryViewState.swift | 2 +- .../Postbox/Sources/MessageMediaTable.swift | 58 ++++-- submodules/Postbox/Sources/Postbox.swift | 9 + .../Sources/PremiumIntroScreen.swift | 2 +- .../BubbleSettingsController.swift | 10 +- .../ForwardPrivacyChatPreviewItem.swift | 2 +- .../Reactions/ReactionChatPreviewItem.swift | 2 +- .../TermsOfServiceControllerNode.swift | 2 +- .../TextSizeSelectionController.swift | 15 +- .../Sources/Themes/EditThemeController.swift | 2 +- .../ThemeAccentColorControllerNode.swift | 21 +-- .../Themes/ThemePreviewControllerNode.swift | 21 +-- .../Themes/ThemeSettingsChatPreviewItem.swift | 4 +- .../Sources/Themes/WallpaperGalleryItem.swift | 4 +- .../Sources/ShareController.swift | 24 +-- .../ShareItems/Sources/ShareItems.swift | 4 +- .../StickerPackPreviewControllerNode.swift | 2 +- .../Sources/StickerPackScreen.swift | 4 +- submodules/TelegramApi/Sources/Api0.swift | 3 +- submodules/TelegramApi/Sources/Api11.swift | 24 +-- submodules/TelegramApi/Sources/Api27.swift | 42 ++++- submodules/TelegramApi/Sources/Api4.swift | 112 ++++-------- submodules/TelegramApi/Sources/Api5.swift | 166 +++++++++--------- submodules/TelegramApi/Sources/Api6.swift | 142 +++++++++------ submodules/TelegramApi/Sources/Api7.swift | 58 ++++++ .../Sources/CallRatingController.swift | 4 +- .../Sources/VoiceChatController.swift | 2 +- .../ApiUtils/StoreMessage_Telegram.swift | 6 +- .../Sources/ApiUtils/TelegramMediaFile.swift | 3 + .../TextEntitiesMessageAttribute.swift | 4 +- .../PendingMessages/EnqueueMessage.swift | 58 +++--- .../PendingMessageUploadedContent.swift | 2 + ...essageAutoremoveTimeoutInteractively.swift | 4 +- .../ManagedSecretChatOutgoingOperations.swift | 6 + .../SyncCore/SyncCore_TelegramMediaFile.swift | 13 ++ ...yncCore_TextEntitiesMessageAttribute.swift | 36 +++- .../TelegramEngine/Messages/AdMessages.swift | 3 +- .../TelegramEngine/Messages/ChatList.swift | 22 ++- .../TelegramEngine/Messages/Message.swift | 9 +- ...OutgoingMessageWithChatContextResult.swift | 28 +-- .../Messages/RequestStartBot.swift | 2 +- .../Stickers/InlineStickers.swift | 5 + .../Stickers/TelegramEngineStickers.swift | 32 ++++ .../Sources/Utils/MessageUtils.swift | 2 +- .../Sources/MessageContentKind.swift | 3 +- .../Sources/ServiceMessageStrings.swift | 27 ++- .../Sources/EmojiTextAttachmentView.swift | 34 ++-- .../Sources/TextNodeWithEntities.swift | 16 +- .../TelegramUI/Sources/AppDelegate.swift | 2 +- .../AuthorizationSequenceController.swift | 2 +- .../TelegramUI/Sources/ChatBotInfoItem.swift | 2 +- .../TelegramUI/Sources/ChatController.swift | 59 ++++--- .../Sources/ChatControllerNode.swift | 8 +- .../Sources/ChatEntityKeyboardInputNode.swift | 2 +- .../Sources/ChatHistoryEntriesForView.swift | 6 +- .../Sources/ChatInterfaceInputContexts.swift | 13 +- .../ChatInterfaceStateContextMenus.swift | 2 +- .../ChatInterfaceTitlePanelNodes.swift | 4 +- .../Sources/ChatMediaInputNode.swift | 2 +- .../Sources/ChatMessageActionItemNode.swift | 40 +++-- .../ChatMessageAttachedContentNode.swift | 2 +- .../Sources/ChatMessageNotificationItem.swift | 2 +- .../Sources/ChatMessageReplyInfoNode.swift | 2 +- ...atMessageRestrictedBubbleContentNode.swift | 2 +- .../ChatMessageTextBubbleContentNode.swift | 4 +- .../ChatPinnedMessageTitlePanelNode.swift | 63 ++++--- .../TelegramUI/Sources/ChatQrCodeScreen.swift | 2 +- .../ChatRecentActionsHistoryTransition.swift | 90 +++++----- .../ChatSearchResultsContollerNode.swift | 2 +- .../Sources/ChatTextInputPanelNode.swift | 2 +- .../LegacyInstantVideoController.swift | 2 +- .../TelegramUI/Sources/OpenChatMessage.swift | 2 +- .../PeerInfoScreenLabeledValueItem.swift | 2 +- .../Panes/PeerInfoVisualMediaPaneNode.swift | 6 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 8 +- .../Sources/ReplyAccessoryPanelNode.swift | 2 +- .../Sources/UpdateInfoItem.swift | 2 +- .../Sources/ChatTextInputAttributes.swift | 8 +- .../Sources/StringWithAppliedEntities.swift | 7 +- .../TooltipUI/Sources/TooltipScreen.swift | 2 +- .../Sources/WatchRequestHandlers.swift | 8 +- 108 files changed, 1005 insertions(+), 678 deletions(-) create mode 100644 submodules/TelegramCore/Sources/TelegramEngine/Stickers/InlineStickers.swift diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index 87464bb853..c7df317a73 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -249,7 +249,7 @@ public enum ChatTextInputStateTextAttributeType: Codable, Equatable { case monospace case textMention(EnginePeer.Id) case textUrl(String) - case customEmoji(stickerPack: StickerPackReference, fileId: Int64) + case customEmoji(stickerPack: StickerPackReference?, fileId: Int64) public init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: StringCodingKey.self) @@ -268,7 +268,7 @@ public enum ChatTextInputStateTextAttributeType: Codable, Equatable { let url = (try? container.decode(String.self, forKey: "url")) ?? "" self = .textUrl(url) case 5: - let stickerPack = try container.decode(StickerPackReference.self, forKey: "s") + 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: @@ -294,7 +294,7 @@ public enum ChatTextInputStateTextAttributeType: Codable, Equatable { try container.encode(url, forKey: "url") case let .customEmoji(stickerPack, fileId): try container.encode(5 as Int32, forKey: "t") - try container.encode(stickerPack, forKey: "s") + try container.encodeIfPresent(stickerPack, forKey: "s") try container.encode(fileId, forKey: "f") } } @@ -400,7 +400,7 @@ public struct ChatTextInputStateText: Codable, Equatable { 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), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) + result.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: nil), range: NSRange(location: attribute.range.lowerBound, length: attribute.range.count)) } } return result 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/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..36c6fe2a12 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)) } } } 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..6a797147fa 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 @@ -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) @@ -1186,10 +1194,10 @@ 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) + 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.last { var composedString: NSMutableAttributedString @@ -1198,15 +1206,16 @@ 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) + 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 let spoilers = spoilers { let mutableString = NSMutableAttributedString(string: messageText, font: textFont, textColor: theme.messageTextColor) for range in spoilers { @@ -1787,7 +1796,14 @@ 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 + )) + let _ = authorApply() let _ = titleApply() let _ = badgeApply(animateBadges, !isMuted) @@ -1862,7 +1878,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 +1888,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 +1917,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 +1931,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 +1940,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 +1999,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 +2011,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 +2261,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/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/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/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift index 2a85754ef1..4e000f2b05 100644 --- a/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift +++ b/submodules/GalleryUI/Sources/ChatItemGalleryFooterContentNode.swift @@ -684,7 +684,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 { 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/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/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 5c991109d9..25d12f558d 100644 --- a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift +++ b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift @@ -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) 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/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/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/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/Pasteboard/Sources/Pasteboard.swift b/submodules/Pasteboard/Sources/Pasteboard.swift index 855805a504..fa4f09165b 100644 --- a/submodules/Pasteboard/Sources/Pasteboard.swift +++ b/submodules/Pasteboard/Sources/Pasteboard.swift @@ -6,7 +6,16 @@ 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) + + if #available(iOS 15.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?\(value.fileId)")!, range: range) + } + }) + } 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) { @@ -60,7 +69,16 @@ private func chatInputStateString(attributedString: NSAttributedString) -> NSAtt 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", let query = url.query { + if let fileId = Int64(query) { + updatedString.removeAttribute(NSAttributedString.Key.link, range: range) + updatedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: fileId, file: nil), range: range) + } + } + }) + return chatInputStateString(attributedString: updatedString) } return nil } 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/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..30f277299e 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,20 @@ 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 let media = self.getMedia(mediaId) { + associatedMedia[mediaId] = media + } + } + } associatedMessageIds.append(contentsOf: attribute.associatedMessageIds) if addAssociatedMessages { for messageId in attribute.associatedMessageIds { @@ -2534,7 +2554,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..70bb530632 100644 --- a/submodules/Postbox/Sources/MessageMediaTable.swift +++ b/submodules/Postbox/Sources/MessageMediaTable.swift @@ -63,7 +63,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 +126,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..105cc1eab1 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) @@ -2295,6 +2300,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 { diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 0dcb18a9b6..22651f3ee6 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -1060,7 +1060,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { 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) + 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( 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/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/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/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/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/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/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/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index 68f071283e..d17a2d11ba 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -399,7 +399,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) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 03355801aa..8ce32224e7 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -467,7 +467,7 @@ private final class StickerPackContainer: ASDisplayNode { 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)) @@ -649,7 +649,7 @@ private final class StickerPackContainer: ASDisplayNode { 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) + 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 diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 430abca038..87f8a9b635 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) } @@ -436,7 +437,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[-727707947] = { return Api.MessageEntity.parse_messageEntityCustomEmoji($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) } diff --git a/submodules/TelegramApi/Sources/Api11.swift b/submodules/TelegramApi/Sources/Api11.swift index 184426636f..7668430ca7 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -7,7 +7,7 @@ public extension Api { case messageEntityBotCommand(offset: Int32, length: Int32) case messageEntityCashtag(offset: Int32, length: Int32) case messageEntityCode(offset: Int32, length: Int32) - case messageEntityCustomEmoji(offset: Int32, length: Int32, stickerset: Api.InputStickerSet, documentId: Int64) + 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) @@ -74,13 +74,12 @@ public extension Api { serializeInt32(offset, buffer: buffer, boxed: false) serializeInt32(length, buffer: buffer, boxed: false) break - case .messageEntityCustomEmoji(let offset, let length, let stickerset, let documentId): + case .messageEntityCustomEmoji(let offset, let length, let documentId): if boxed { - buffer.appendInt32(-727707947) + buffer.appendInt32(-925956616) } serializeInt32(offset, buffer: buffer, boxed: false) serializeInt32(length, buffer: buffer, boxed: false) - stickerset.serialize(buffer, true) serializeInt64(documentId, buffer: buffer, boxed: false) break case .messageEntityEmail(let offset, let length): @@ -196,8 +195,8 @@ public extension Api { 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 stickerset, let documentId): - return ("messageEntityCustomEmoji", [("offset", String(describing: offset)), ("length", String(describing: length)), ("stickerset", String(describing: stickerset)), ("documentId", String(describing: documentId))]) + 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): @@ -335,18 +334,13 @@ public extension Api { _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() - var _3: Api.InputStickerSet? - if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.InputStickerSet - } - var _4: Int64? - _4 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() let _c1 = _1 != nil let _c2 = _2 != nil let _c3 = _3 != nil - let _c4 = _4 != nil - if _c1 && _c2 && _c3 && _c4 { - return Api.MessageEntity.messageEntityCustomEmoji(offset: _1!, length: _2!, stickerset: _3!, documentId: _4!) + if _c1 && _c2 && _c3 { + return Api.MessageEntity.messageEntityCustomEmoji(offset: _1!, length: _2!, documentId: _3!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index 9b4000c6a8..1f202e0395 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -3965,6 +3965,25 @@ public extension Api.functions.messages { }) } } +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() @@ -4115,6 +4134,21 @@ public extension Api.functions.messages { }) } } +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() @@ -6245,12 +6279,12 @@ public extension Api.functions.payments { } } public extension Api.functions.payments { - static func assignPlayMarketTransaction(purchaseToken: String, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func assignPlayMarketTransaction(receipt: Api.DataJSON, purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-179907586) - serializeString(purchaseToken, buffer: buffer, boxed: false) + buffer.appendInt32(-537046829) + receipt.serialize(buffer, true) purpose.serialize(buffer, true) - return (FunctionDescription(name: "payments.assignPlayMarketTransaction", parameters: [("purchaseToken", String(describing: purchaseToken)), ("purpose", String(describing: purpose))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + 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() { 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/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/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/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 11668c41b7..6427a34b34 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -374,10 +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 .messageEntityCustomEmoji(offset, length, stickerset, documentId): - if let stickerPack = StickerPackReference(apiInputSet: stickerset) { - result.append(MessageTextEntity(range: Int(offset) ..< Int(offset + length), type: .CustomEmoji(stickerPack: stickerPack, fileId: documentId))) - } + 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/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift index e8517f499d..a15122379f 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift @@ -102,6 +102,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 6c3e4b7dcb..85014d0805 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/TextEntitiesMessageAttribute.swift @@ -48,8 +48,8 @@ func apiEntitiesFromMessageTextEntities(_ entities: [MessageTextEntity], associa apiEntities.append(.messageEntityBankCard(offset: offset, length: length)) case .Spoiler: apiEntities.append(.messageEntitySpoiler(offset: offset, length: length)) - case let .CustomEmoji(stickerPack, fileId): - apiEntities.append(.messageEntityCustomEmoji(offset: offset, length: length, stickerset: stickerPack.apiInputStickerSet, documentId: fileId)) + case let .CustomEmoji(_, fileId): + apiEntities.append(.messageEntityCustomEmoji(offset: offset, length: length, documentId: fileId)) case .Custom: break } diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index e37d1f813f..9c8ebeaf60 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 } } @@ -370,7 +370,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 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/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/State/ManagedSecretChatOutgoingOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSecretChatOutgoingOperations.swift index 50b56a3a48..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 diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index 2ca2f540f6..df9fbc310d 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -11,6 +11,7 @@ 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, Codable { case id(id: Int64, accessHash: Int64) @@ -188,6 +189,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) @@ -217,6 +219,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() } @@ -273,6 +277,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") + } } } } diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TextEntitiesMessageAttribute.swift index 7c6bbe7d3d..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 CustomEmoji(stickerPack: StickerPackReference, fileId: Int64) + case CustomEmoji(stickerPack: StickerPackReference?, fileId: Int64) case Custom(type: CustomEntityType) } @@ -73,11 +73,8 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { case 17: self.type = .Spoiler case 18: - if let stickerPack = decoder.decodeObjectForKey("s", decoder: { StickerPackReference(decoder: $0) }) as? StickerPackReference { - self.type = .CustomEmoji(stickerPack: stickerPack, fileId: decoder.decodeInt64ForKey("f", orElse: 0)) - } else { - self.type = .Unknown - } + 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: @@ -134,7 +131,7 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { case 17: self.type = .Spoiler case 18: - self.type = .CustomEmoji(stickerPack: try container.decode(StickerPackReference.self, forKey: "s"), fileId: try container.decode(Int64.self, forKey: "f")) + 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) @@ -187,7 +184,11 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { encoder.encodeInt32(17, forKey: "_rawValue") case let .CustomEmoji(stickerPack, fileId): encoder.encodeInt32(18, forKey: "_rawValue") - encoder.encodeObject(stickerPack, forKey: "s") + 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") @@ -241,7 +242,7 @@ public struct MessageTextEntity: PostboxCoding, Codable, Equatable { try container.encode(17 as Int32, forKey: "_rawValue") case let .CustomEmoji(stickerPack, fileId): try container.encode(18 as Int32, forKey: "_rawValue") - try container.encode(stickerPack, forKey: "s") + 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") @@ -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/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/TelegramEngineStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift index c064783ab5..6572932b23 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 { @@ -155,5 +156,36 @@ public extension TelegramEngine { } |> ignoreValues } + + public func resolveInlineSticker(fileId: Int64) -> Signal { + return self.account.postbox.transaction { transaction -> TelegramMediaFile? in + return transaction.getMedia(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) as? TelegramMediaFile + } + |> mapToSignal { cachedFile -> Signal in + if let cachedFile = cachedFile { + return .single(cachedFile) + } + + return self.account.network.request(Api.functions.messages.getCustomEmojiDocuments(documentId: [fileId])) + |> map(Optional.init) + |> `catch` { _ -> Signal<[Api.Document]?, NoError> in + return .single(nil) + } + |> mapToSignal { result -> Signal in + guard let result = result else { + return .single(nil) + } + return self.account.postbox.transaction { transaction -> TelegramMediaFile? in + for document in result { + if let file = telegramMediaFileFromApiDocument(document) { + transaction.storeMediaIfNotPresent(media: file) + } + } + + return transaction.getMedia(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)) as? TelegramMediaFile + } + } + } + } } } 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/TelegramStringFormatting/Sources/MessageContentKind.swift b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift index 49fd545979..dcaf7fa6ce 100644 --- a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift +++ b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift @@ -1,4 +1,5 @@ import Foundation +import Postbox import TelegramCore import TelegramPresentationData import TelegramUIPreferences @@ -111,7 +112,7 @@ public func messageTextWithAttributes(message: EngineMessage) -> NSAttributedStr 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) + 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) diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index e9ca6c3d49..9d3bbd9f01 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: "")]) } @@ -176,9 +181,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 +270,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 +582,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): diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index 630b33ea0e..2a534c0b22 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -54,7 +54,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } } - public init(context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) { + public init(context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) { self.context = context self.groupId = groupId self.emoji = emoji @@ -68,23 +68,19 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { super.init() - self.infoDisposable = (context.engine.stickers.loadedStickerPack(reference: emoji.stickerPack, forceActualized: false) - |> deliverOnMainQueue).start(next: { [weak self] result in - guard let strongSelf = self else { - return - } - switch result { - case let .result(_, items, _): - for item in items { - if item.file.fileId.id == emoji.fileId { - strongSelf.updateFile(file: item.file, attemptSynchronousLoad: false) - break - } + if let file = file { + self.updateFile(file: file, attemptSynchronousLoad: true) + } else { + self.infoDisposable = (context.engine.stickers.resolveInlineSticker(fileId: emoji.fileId) + |> deliverOnMainQueue).start(next: { [weak self] file in + guard let strongSelf = self else { + return } - default: - break - } - }) + if let file = file { + strongSelf.updateFile(file: file, attemptSynchronousLoad: false) + } + }) + } } override public init(layer: Any) { @@ -179,8 +175,8 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { public final class EmojiTextAttachmentView: UIView { private let contentLayer: InlineStickerItemLayer - public init(context: AccountContext, emoji: ChatTextInputTextCustomEmojiAttribute, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { - self.contentLayer = InlineStickerItemLayer(context: context, groupId: "textInputView", attemptSynchronousLoad: true, emoji: emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: 24.0, height: 24.0)) + public init(context: AccountContext, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { + self.contentLayer = InlineStickerItemLayer(context: context, groupId: "textInputView", attemptSynchronousLoad: true, emoji: emoji, file: file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: 24.0, height: 24.0)) super.init(frame: CGRect()) diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index f45bd8eed8..724c187b04 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -7,13 +7,16 @@ 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, fontSize: CGFloat) { + init(emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, fontSize: CGFloat) { self.emoji = emoji + self.file = file self.fontSize = fontSize } @@ -26,6 +29,9 @@ private final class InlineStickerItem: Hashable { 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 } @@ -95,7 +101,7 @@ public final class TextNodeWithEntities { 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: ChatTextInputTextCustomEmojiAttribute(stickerPack: value.stickerPack, fileId: value.fileId), fontSize: font.pointSize), range: range) + string.addAttribute(NSAttributedString.Key("Attribute__EmbeddedItem"), value: InlineStickerItem(emoji: value, file: value.file, fontSize: font.pointSize), range: range) } } }) @@ -159,7 +165,7 @@ public final class TextNodeWithEntities { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) self.inlineStickerItemLayers[id] = itemLayer self.textNode.layer.addSublayer(itemLayer) @@ -267,7 +273,7 @@ public class ImmediateTextNodeWithEntities: TextNode { 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: ChatTextInputTextCustomEmojiAttribute(stickerPack: value.stickerPack, fileId: value.fileId), fontSize: font.pointSize), range: range) + string.addAttribute(NSAttributedString.Key("Attribute__EmbeddedItem"), value: InlineStickerItem(emoji: value, file: value.file, fontSize: font.pointSize), range: range) } } }) @@ -322,7 +328,7 @@ public class ImmediateTextNodeWithEntities: TextNode { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) self.inlineStickerItemLayers[id] = itemLayer self.layer.addSublayer(itemLayer) diff --git a/submodules/TelegramUI/Sources/AppDelegate.swift b/submodules/TelegramUI/Sources/AppDelegate.swift index a4e7eb3681..ce15158246 100644 --- a/submodules/TelegramUI/Sources/AppDelegate.swift +++ b/submodules/TelegramUI/Sources/AppDelegate.swift @@ -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/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/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index bc2a24f695..a05f8bdb55 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1499,7 +1499,7 @@ 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)]) + 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 @@ -1596,7 +1596,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } } - 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) @@ -1634,7 +1634,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) @@ -1968,7 +1968,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)) } @@ -1992,7 +1992,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)]) } }) } @@ -2034,7 +2034,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) { @@ -2337,7 +2337,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)]) } })) } @@ -6044,7 +6044,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) } @@ -7256,7 +7256,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 } @@ -10635,7 +10635,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 { @@ -11011,7 +11011,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 { @@ -11048,7 +11048,7 @@ 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.updateChatPresentationInterfaceState(animated: true, interactive: false, { @@ -11081,7 +11081,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] = [] @@ -11118,7 +11118,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, 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) } } @@ -11182,7 +11182,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 @@ -11205,7 +11205,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) @@ -11637,7 +11637,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 { @@ -11963,7 +11963,7 @@ 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.updateChatPresentationInterfaceState(animated: true, interactive: false, { @@ -12018,7 +12018,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, 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) } } @@ -12077,7 +12077,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, 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 @@ -12095,7 +12095,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) } }, 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) @@ -12420,6 +12420,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, @@ -12539,7 +12540,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) @@ -12562,9 +12563,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 @@ -12837,7 +12838,7 @@ 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({ @@ -13100,7 +13101,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, 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 @@ -13195,7 +13196,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } }, 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 { @@ -14098,7 +14099,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)) } } } @@ -14589,7 +14590,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()) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index db2c38c78f..fbe73c17ca 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -964,7 +964,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 @@ -2820,7 +2820,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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) @@ -2838,14 +2838,14 @@ 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)) + messages.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], 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)) + messages.append(.message(text: "sleep\(i)", attributes: [], inlineStickers: [:], mediaReference: nil, replyToMessageId: nil, localGroupingKey: nil, correlationId: nil)) } } #endif diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 9ea40f893a..fbf1eca0c6 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -52,7 +52,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { case let .Sticker(displayText, packReference, _): text = displayText if let packReference = packReference { - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: item.file.fileId.id) + emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: item.file.fileId.id, file: item.file) break loop } default: diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift index 19bfb4cdf8..4443671406 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: [:] ) } @@ -323,7 +324,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/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index a275b87060..3e8289094b 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift @@ -272,8 +272,17 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte case .inputButtons: return ChatTextInputPanelState(accessoryItems: [.keyboard], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) case .none, .text: - if let _ = chatPresentationInterfaceState.interfaceState.editMessage { - return ChatTextInputPanelState(accessoryItems: [], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) + if let editMessage = chatPresentationInterfaceState.interfaceState.editMessage { + let isTextEmpty = editMessage.inputState.inputText.length == 0 + + let stickersAreEmoji = !isTextEmpty + + var stickersEnabled = true + stickersEnabled = true + + accessoryItems.append(.stickers(isEnabled: stickersEnabled, isEmoji: stickersAreEmoji)) + + return ChatTextInputPanelState(accessoryItems: accessoryItems, contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) } else { var accessoryItems: [ChatTextInputAccessoryItem] = [] var extendedSearchLayout = false 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/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/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index fbcf89e302..9d952b1199 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -1455,7 +1455,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) diff --git a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift index 92919b03df..3cd58a48c5 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 @@ -42,9 +43,9 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { private var absoluteRect: (CGRect, CGSize)? 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 +56,7 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { super.init() - self.addSubnode(self.labelNode) + self.addSubnode(self.labelNode.textNode) } required init?(coder aDecoder: NSCoder) { @@ -130,7 +131,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 +274,15 @@ 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 + )) 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 +295,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) }) @@ -367,9 +373,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 +385,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 +409,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 +423,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/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift index 77fe6da306..ed841436f1 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift @@ -393,7 +393,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)) } diff --git a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift index d61ba7bd2a..06cecfc2fd 100644 --- a/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift +++ b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift @@ -310,7 +310,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) } diff --git a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift index 6eabcd003c..4e6f278640 100644 --- a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift @@ -177,7 +177,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode { } } if entities.count > 0 { - 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) + 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.string, font: textFont, textColor: textColor) } 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/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index d6a2bb8278..d095151145 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -301,7 +301,7 @@ 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 { @@ -321,7 +321,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { 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) + updatedAttributes[ChatTextInputAttributes.customEmoji] = ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: item.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) diff --git a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index 10382a35e1..59f7725103 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,7 +55,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { private let contentTextContainer: ASDisplayNode private let lineNode: AnimatedNavigationStripeNode private let titleNode: AnimatedCountLabelNode - private let textNode: TextNode + private let textNode: TextNodeWithEntities private var spoilerTextNode: TextNode? private var dustNode: InvisibleInkDustNode? private let actionButton: HighlightableButtonNode @@ -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,19 +512,19 @@ 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 makeTextLayout = TextNodeWithEntities.asyncLayout(self.textNode) let makeSpoilerTextLayout = TextNode.asyncLayout(self.spoilerTextNode) let imageNodeLayout = self.imageNode.asyncLayout() @@ -640,15 +648,16 @@ 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.string), font: textFont, textColor: textColor) } @@ -669,7 +678,17 @@ 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 + ) + } + let _ = textApply(textArguments) strongSelf.previousMediaReference = updatedMediaReference @@ -678,7 +697,7 @@ 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() @@ -688,7 +707,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { spoilerTextNode.contentMode = .topLeft spoilerTextNode.contentsScale = UIScreenScale spoilerTextNode.displaysAsynchronously = false - strongSelf.contentTextContainer.insertSubnode(spoilerTextNode, aboveSubnode: strongSelf.textNode) + strongSelf.contentTextContainer.insertSubnode(spoilerTextNode, aboveSubnode: strongSelf.textNode.textNode) strongSelf.spoilerTextNode = spoilerTextNode } 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/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/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index b5b3e34d4d..ec4bbb20e1 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 diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 76487a0605..889de57d64 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -794,7 +794,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { return UIView() } - return EmojiTextAttachmentView(context: context, emoji: emoji, cache: presentationContext.animationCache, renderer: presentationContext.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12)) + return EmojiTextAttachmentView(context: context, emoji: emoji, file: emoji.file, cache: presentationContext.animationCache, renderer: presentationContext.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12)) } } } diff --git a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift index a5bd2aa3c8..c08dd6594f 100644 --- a/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift +++ b/submodules/TelegramUI/Sources/LegacyInstantVideoController.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index dd1db1ddce..54a491d847 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) 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 d1064dcaa8..8dc1c40b17 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -4971,7 +4971,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))) } @@ -5385,7 +5385,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))) @@ -5506,7 +5506,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) @@ -6594,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)) } } } diff --git a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift index 54b0552aee..3d9e461324 100644 --- a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift @@ -151,7 +151,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { } 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/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 3bdae8b476..8d3924042d 100644 --- a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift +++ b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift @@ -220,19 +220,21 @@ public final class ChatTextInputTextUrlAttribute: NSObject { } public final class ChatTextInputTextCustomEmojiAttribute: NSObject { - public let stickerPack: StickerPackReference + public let stickerPack: StickerPackReference? public let fileId: Int64 + public let file: TelegramMediaFile? - public init(stickerPack: StickerPackReference, fileId: Int64) { + 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.stickerPack == other.stickerPack && self.fileId == other.fileId + return self.stickerPack == other.stickerPack && self.fileId == other.fileId && self.file?.fileId == other.file?.fileId } else { return false } diff --git a/submodules/TextFormat/Sources/StringWithAppliedEntities.swift b/submodules/TextFormat/Sources/StringWithAppliedEntities.swift index ad3588a8b4..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 { @@ -41,7 +42,7 @@ public func chatInputStateStringWithAppliedEntities(_ text: String, entities: [M 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), range: range) + string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId, file: nil), range: range) default: break } @@ -49,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 @@ -250,7 +251,7 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti } } case let .CustomEmoji(stickerPack, fileId): - string.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: stickerPack, fileId: fileId), range: range) + 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/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/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 { From e27ec389b1f6758ac23bcbfee4aed5a0593a88fa Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 9 Jul 2022 19:11:24 +0200 Subject: [PATCH 039/113] Various improvements --- .../Resources/{Gift.tgs => Gift1.tgs} | Bin Telegram/Telegram-iOS/Resources/Gift2.tgs | Bin 0 -> 53946 bytes Telegram/Telegram-iOS/Resources/Gift3.tgs | Bin 0 -> 54100 bytes .../Telegram-iOS/en.lproj/Localizable.strings | 3 ++ .../Sources/AttachmentContainer.swift | 13 +++++++++ .../Sources/AttachmentController.swift | 22 ++++++++++++++ .../Sources/MediaPickerScreen.swift | 8 ++++++ .../PremiumUI/Sources/PremiumGiftScreen.swift | 18 ++++++------ .../Sources/PremiumIntroScreen.swift | 2 +- .../Sources/ChatMessageGiftItemNode.swift | 21 +++++++++++--- .../WebUI/Sources/WebAppController.swift | 27 ++++++++++++++++-- versions.json | 2 +- 12 files changed, 100 insertions(+), 16 deletions(-) rename Telegram/Telegram-iOS/Resources/{Gift.tgs => Gift1.tgs} (100%) create mode 100644 Telegram/Telegram-iOS/Resources/Gift2.tgs create mode 100644 Telegram/Telegram-iOS/Resources/Gift3.tgs diff --git a/Telegram/Telegram-iOS/Resources/Gift.tgs b/Telegram/Telegram-iOS/Resources/Gift1.tgs similarity index 100% rename from Telegram/Telegram-iOS/Resources/Gift.tgs rename to Telegram/Telegram-iOS/Resources/Gift1.tgs diff --git a/Telegram/Telegram-iOS/Resources/Gift2.tgs b/Telegram/Telegram-iOS/Resources/Gift2.tgs new file mode 100644 index 0000000000000000000000000000000000000000..59d727cdf5185496dcfa031f908bd7c123f96a86 GIT binary patch literal 53946 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

U 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 literal 0 HcmV?d00001 diff --git a/Telegram/Telegram-iOS/Resources/Gift3.tgs b/Telegram/Telegram-iOS/Resources/Gift3.tgs new file mode 100644 index 0000000000000000000000000000000000000000..ba9a105858a44bf2082107022e5db7d6fdb1bbcf GIT binary patch literal 54100 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

hi{{N7ZKQfX{r9_*w3uao93x0H;mH|u zZ(&$&-d(B`i;M8MYPargdk1|N!>{5_f7!$iFd5e8yv2Lt9EazdMdFezF-{XSy@9eD zTcPD$(gp;8OE!khzznCz1-u@ix-K@|Bz4VfDrt$)9mdGi znA(*y!7s8^#pxXT*~5#NVvut(+ucADJ)pVFdJwX59AXiJut9R$qX`rE(ElsmjBUY{PJ{X_kqngU7~70qqe8*n;$> zXX8%TvL0#i+`*659XM+J3T*Vz%r3w2+yI{BV`_D(*cEMo(H`5HPvEJM_AcS)qr@CQ zXH9EK3f(dcWG=V7nb6m8s-5A>=679Y6iB{`V2fqbjX0iv7nLlmhyoh->9JubGar(K zI*?4W*jg!>U`mP|sGe>@?BnS{2__ictz_EDVlPxSSV;Up1`|$?41(fnw}9Ei77hf% zZsv9V&F65I)xGyY+)C}f@F14l?p+V!W@2~$gQ!hKMeIy|78NOd;H|Prm$|Vwp!3b4 z&4CD!oXPg)rU%ujV%m!DcoLs^-2?JEB6q;XcNC+!PV8c(cMRGABX4^c^2A?zIpW-$Hx0= zr!k&)8h`hj-@T*N=o>5?53x%r>sF`H-jZ1HOHbWsgxAG^u0!H66=s}Lj}g*#%QLW5 zcQqDWSa^Z77B^c3cnfq>=vB(fY*gkL`uz6s&D*D=CWoRYk8d=S#9i(>l&V1H6m1sp z*i4a%=MUXA)l=J)dUDY^3E%`sj@S$JkziVBI$T+Owi5)}8_IQhVW1tG^=H-JJ9&o~ zcynPHyBEFO!&>*xS=~{gmrAEh=#f5ICNE3&MK>-cvNS~bJ?-5aqc|0}>S^6dS!iL} zyFtLy)Uu8g3!6BxpN%I&iV{?24gN@PG0d`T5mL$wQl`OoPDFb8rC*FlHy=csMevX~ zs=z)6;#|5GD()hhDt7>T-RSMVlC04wmRcvQB0w zOp440B$Bn0+>~=mjiBI=`fW^Bzq-Y4DF3SmFJq=)WDq=Yi$K$<9yg|PpbQcyQMVqv z+LOm*`pcfFI=BMM9d;U}rfgmKLet!484Zcro6&0EGf(vLcs~&9KYn{x&-q(PS%0Q>ys{6-=3hFrQ$J3DI z^A;i^K=uld$AA9UpKw?BZ@9SAf1F3pTTuDnF#2MsGGFNQ1xGnV$hFRW7*;a32B?wA zSy%+T9-Ah6G-SPB0Il60Gb0tF1Wcq1)pN(p>D@sysru~@8;V0WgXZ}TP)(jEXdY3< z^R`1Q%P&%Tqvn~2`AuGOn=nODy<1`v(-5mE!K{+25V|V1bcNT*^mLP$XcdOZDYPUO z45vpvl^mdW%Cf|yNH(^Nr|5#sYi&nOY6ioc3V2;v$N#43Zj5EWl%7`vZT% zmlpGoE1o42;4>(%1&kXGdJ2f_8{2L*PR|3>47#dZww&1*9NC6Z)PEWkaskjsh~~PI z75Dji)o1dwCg8QJu$b^<5gm}VbP>F^M_(n`6PC_+(N zJxEJ%+7E_Gk|~u)g8m%9coEjHa_0EyZbcs)mXLRjowxC(a~}DRHsFpjh{E*XmRTZR z2iwb^rx*dKA^=F?x~T`Z3mo_wY+AwzujRRF|xO8h7^TqpDz=Qn8gXpH9sIU|JW=S)k2NV zJtui5pwP{1;npNa>5_Q@%K6zi_QfccqDDih_(0cX_5Csgfr0V2HeeI-tebTZVO=Ua z6PKdExx8u7^0lG=Y1r9MGyUi)889S~+pv2LdpR3+c%{r2$#THBU(a{%Hzyd3J0hZN zy&AA&Fz)?)+&S!1m#ApaJ_T@YD-JSLE9Z-3KC^&08t5=!pJ?WlhhaIr&5Q8^oy_$;Ia&zH1P_UIV9(xH;66g~n)(|9IaSb~yf(cff@{Qf}MP z9VP+J?#q)0%;ntybBmNFO{KE#bE`^f?*Mg9?|6=Y`HAsE&O}(uQfZ7ItmN_pngkI; zy2+bRVk+`v+LXFXhzfqWrqxZ|;Yt3)UsEteCqFvPk=Wq0N)j}1yip#e?g1j$C@rf# z-NE`~3N#gUolF-B)JJ!&*kVllHYO-GLv&*vp*r=7(e#3RztL@7D%eh5Z#wqr7Dl|z z97aGR;IC>-gmIHN{oCT=12|{^JVMH1kkxFWMaXsh5@Uoi9GL6=C0oQ1 zgm_sIp6nq_5^tvKP1KS=Z4o}_r8YVC-ewFx6Uy<1JTvfz><0T(20{f3dL(^i4zhbk zGps%_^+j@R@+A)5mS7r*1hC*X$Q!u}n zDpI@wC-(KJf?&?0eI)NST7eN;PTeex0*}s&f~8^ltxetiV`{d}=hLW^Oo&q1&hbp@ zL^4=-k;+H%akZ*J#gW5eDKpELlB5y^#uS#^l_-zN$Yk><-$_nF1< ziF3qXz0Y59`8KNFll!>L?b0og8bul9uc>Mas?C^OhI>$nmZlvqRq|L1}Y4VuMi0x)%%XzQACq9$XR`-BwR2tz8C1k0<|IF-3VKnm;}Y1Mx+eJ8Oj6a9If4a zprM$Vqc)O<1#Xb*HUY1+?2~C(qbBFEqggJ%L3bU@I0H`r$*u#{)v|XSP1NLJ&Jmp5 zHAxzN(ySZjxgZE$0~eUg^N-bvc_u$a8U(5w3k$d?%t6W~oM8_A!^zsZWRqha zv^vL~OlvrfPG4m9n%!z!3=<14^{3dT7C8;gax^pzIBp0)@fSk5AZ$fPJX#6a;_&Hm{{=Fa~+2%87;Ma?ObO)6@}|OZQ{AjAFVis-6(+FDQRig(UgsZ$oSs_A{^cp==uuO_SJ}c>8N#J zbZkhxc@0`g!OLD-#qPQddayyqkS_wN7b70Ymzyd~`m$}jft?2vG*3bH#?ckCo};b7 zUiBg?b@nmO`(#PM>;$0D%5|4b1~_fQ%?2Nha+I@$F{|L1rqd*XWkW!A%Xa~;zc_@z zJxgZ1*zrXMcqP^Q zf>Ba5Q$+Ql%Jxrvq-eQQFDrIWLG}lP%XznGxxF`94zAH=IR#23-BQr8cf_9ABX}Bl z_I?*KI8S77eia#^j7i^ijXvP;Z5SNa#V*tb6(Nd326h{C@RMlH3x}(t?rdE&WU(-0*gWrUT z(h^$&+g2Eyn~&=lhK15|(l|?c# zt7LVGMjv6es8UnxK= z{OaZ(--V@M$(Hsq)MuUo%c;;tIjqgf3Z5!b2DyOHy$xu}?u`OfC6TTaO7%D}V|T$3 zw>PKCG&5Hu0pg#hX;!u66U4V}uTB&J8aN zOOREk#V|Pd$jHvw(ho-$9iT9t+_9y7kEuyITX?3Q`T zQYAL%5z!h`y<`7su0K;nIuMq9U6IbQ-T^2cI|kTLNOc?{S08Rmi2zxK!zOfy!t`HF zae8v?Dwh8&Pgf2hp<9$yzXMksq&m@H=W;zjl~+S1oAOQ-YQ);m#EpeV!jqS%-Md9r z8k(MPyP!(ct%z~H1L9vjJWq)_K0B@$hX~8krkB#CJ)ex(8%xIIoM4h)78yd$l zP)o49yC6CPw8?7RW(?^G`3)3phZ%370m{+oh zsoS`BKy3*3VrH&Iz6RaL6J;tGrC7xQDVdujHK=VLRMEGw9-(HRLX?QHJRMPF zyG8OK=C`$qy8N&AG5ct@#ycr1MU=qX4OIes~!T^z6! zQ6Z**)%E-~RZs-F#)RnH*s@FO&Qd8u2|etrF^4e~Qpi4Knq2L)Kbun=+}&zm9sIdg z4ttuaP|*`^tfHZ(b_|Je@ev7u&Gbms6woU*@hu}#gv>ZlegUU($GSyRaE>393vbSJ zxE{wj?J}h|-9$}I+DKe9n~Gpk(U5ey_VrvBs5=;SqSGps=>I7#@3<1}&vfpxi_d7UBfcX9Y;(9k0gutfZ`=YB1B^mVpj`|GI1vmEiI5y zArnj%@ea>?Yj!4WKzVirque%ELB2@8xERd`z&uUHPBKpOZuO{!?{0z3Ve8M23uS00 zmfh>O0R95hJjHqeIQNv}P$N4~w!)Mh382Kz?x>b~s#*cPK^5z&%^K}QL^X!0B`}zR zhRtF~LdOA)SOWHR;7adO!+=~Js{E#=M*C_C(KF34EyMBSb74TUe`xsjjB#`X$2n>O zdS9F}@p{TQngTGDE3Zu%Bz_I^>70ggWCAUL4J2CQq#ec0(#~=UzCpU>0#B-!pmCdNFBea)7}x zsx1V{yj<9|p)jr1cRSN$rB5l**QwrD(S6_Djwx#^Bz@#w$uLd}#_jrE3w!zpnF?H?Ux1=SAvLFKrxKtZ{GYk!`beG6!}e@ zbqG4zC7r!Ty*9J?aY#;jzRw+izF!nOBfJJk0@#{c@#lPl0}JTMNo`*Pk;vx|iGTX} zKPk+1zf)5q#Vl1FXSbc2uHJJW0OEa-^6e0)oyCP0kkCGsnqix#1+K%wj5=-Ms>jAk zWs^Qdu=7=wL+4Jd-fUaAT2mBjntDirD)(-1LvMx33Epa`Dv#ZHRTJW51Ke5FRV)1k zm8H9=_G#*Q!ppnK*=dq$Dj=q@Slpj`qWyvI^RELjloKBrSdB)|+63MncVEdr+|C`y z@sm-;NR0S;@~AQ+)@m5v;4KpvFQh8pr!0$y@ez+fF4@jZRx1&4!yDU8%`iVU{4zzT zi3o@XTts4{U7<1{0pY_i27i$*p~A^BhBK?fvsvJ%P=yR9-I@iSwU(qt0m?eEf%3k- za}u;yCIL}0ngs$X!#<%JyMTrH%C#7g6h(1?!@fYYqT+@Rxsy2Y*81e_6cFx+GMr_}(yI6s*TiL?<4-377{;&-p z!#|Z6rW|)V6+XHlcnXVz>2dbfevn?<54w}~cr~A#o-jC=@P+r)BV7fV_37-owH-tN zG&02`>|J* zVVqOsZ|b&4k`PRW3E#`=*y+BY#+{{*6Ytv$JctUNs+^}efP;2>=1B5`=75nKSQsFr zP}hKRBljh_N(MIFREUt5Dk^b#n*s6lt)OzG@I?EnRau<+MUp9uoHm#&+&pOyB40iF zQe)Sz^mCpTyI@ol%(N0_423!e{Ts4<^VL3pM%;)CK+ZJ`D*BPxT&X_t^wZ6tz@4zK zzISqYl5GK0^v>EUQ|DxuO%Xo)B$|=W#3!N;nC}V+963ZmK(S>9poF+F(H&<9pT0MR zec?%+o4ZJ(q)ZWP0QS;|?5fNvVL-?Ypv0RS0KK5`_tskM5vAW&;=29;(?iEIY5Bt@ zFN~*TMg>G}f-R*T31K1TXDRbw0QXKdF(RK}_0#nW%c+$3NX;Y8VPVFme+~}mmax*^t!XOf3Z*0ukil8oC5VyNxgWvI?iO^D>s0I(kJX0 zC$ubx!(|X|Kz=2${?_uZfkFdQs$#$857l8f+)iZn`Qk6EkD&HkR`te0yicDJAfA9m zyb$LeMrk_myr%;u*{u)~QV3fRAs224QQZ&n%RE)!Eq6}D-yKlS&sKYPV|HQ+#d%^x zL3}CFaif}l*%-yzNT+p;h<;ty0R7E%jmJh>UzvDw>;Xr%OKoK%L82X)y&*TQ%WR%a zaA;M5$f_+4W|VZnUR6j?>piV)C;k2~@%=rYuWfwC*fLrF!Gd8^wpO(h<4B_L1&ZrC zU6>1Wdjw>{Q)Ad46caRJkLuD<@ldI$l71`F*GB!fs@E0e)iz$q01e0KvIF}gO!=_|9Vyec4vpg zo0o`K;AhvE6~qr+WR{=ehc05Ji{po`GE?9Dk&Da>>SI4;2I3$3DKnlsmJeOUeoDB! zNQie|W1c`G54``U)XOZnSCbY;|DD%pXV+L22%L82Kkw3?@r?!Eu}M}o zj>oU~>(AO7^@o4o{_uhN|H!*pRg9=^qZ_^N*Ua?|Wl#vz#HteP-d{8420FADv&MjV z@2{C#1gu(#Vybjv+xu(M_G}vMg(8@%b@yj8cNt$z6{aBK_IrQL+=qgzV%oP#d568f zX5LNCOy(nWV&3y;-UBiWkg!9^yQh~O9?WgrUU1UU7}2qD?{^)rxfS{b;)Lj0&b{Ym zu{s51C14K z#KDK{UmyCax$y%j>caL_XFL14d#-q>CAs!guzNGR?iT_#*NHU}@V5Y5%jxm^w<;C8 zpthXBB26r#qiv09vUsMfv6~2WAfte^p{c#xWtzYiNPJNNG#Ldnk)rDQliAZ-Mg1N< zj}a#(KjB@tyBKYlQA`YIgG89=bZhnz+Xk(QGW(|V&4V@M#0H5B4e7VFCiv9_!8%4e zl<0i{_!{ee1h=8bkqtancnpKqpt>lBtEUFl`n$DjKNtSfEqw43Q1*u*J=Z;8&Yec< zTJ?nlYib51BmGd92А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 literal 0 HcmV?d00001 diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 3c0613cc7c..39090862be 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7840,3 +7840,6 @@ Sorry for the inconvenience."; "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"; diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index acb3bd1be9..b4edaed71c 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -37,6 +37,8 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { var interactivelyDismissed: (() -> Void)? var controllerRemoved: ((ViewController) -> Void)? + var shouldCancelPanGesture: (() -> Bool)? + var updateModalProgress: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private var isUpdatingState = false @@ -232,6 +234,11 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { } } + if translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() { + self.cancelPanGesture() + return + } + var bounds = self.bounds if self.isExpanded { bounds.origin.y = -max(0.0, translation - edgeTopInset) @@ -340,6 +347,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..0d792e7619 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -83,6 +83,7 @@ public protocol AttachmentContainable: ViewController { func prepareForReuse() func requestDismiss(completion: @escaping () -> Void) + func shouldDismissImmediately() -> Bool } public extension AttachmentContainable { @@ -101,6 +102,10 @@ public extension AttachmentContainable { func requestDismiss(completion: @escaping () -> Void) { completion() } + + func shouldDismissImmediately() -> Bool { + return true + } } public enum AttachmentMediaPickerSendMode { @@ -312,6 +317,23 @@ public class AttachmentController: ViewController { } } + self.container.shouldCancelPanGesture = { [weak self] in + if let strongSelf = self, let currentController = strongSelf.currentControllers.last { + if !currentController.shouldDismissImmediately() { + currentController.requestDismiss { [weak self] in + if let strongSelf = self { + strongSelf.controller?.dismiss(animated: true) + } + } + return true + } else { + return false + } + } else { + return false + } + } + self.panel.selectionChanged = { [weak self] type in if let strongSelf = self { return strongSelf.switchToController(type) diff --git a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift index 3206e391f0..50cb36cb20 100644 --- a/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift +++ b/submodules/MediaPickerUI/Sources/MediaPickerScreen.swift @@ -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/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index a1188dd1ef..370322e728 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -846,12 +846,14 @@ private final class PremiumGiftScreenComponent: CombinedComponent { } }, completed: { [weak self] in if let strongSelf = self { - let _ = updatePremiumPromoConfigurationOnce(account: strongSelf.context.account).start() - strongSelf.inProgress = false - strongSelf.updateInProgress(false) - - strongSelf.updated(transition: .easeInOut(duration: 0.25)) - strongSelf.completion(duration) + 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) + } } })) } @@ -1265,8 +1267,8 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) } navigationController.setViewControllers(controllers, animated: true) - Queue.mainQueue().after(0.1, { - if let topController = navigationController.viewControllers.first { + Queue.mainQueue().after(2.8, { + if let topController = navigationController.viewControllers.last { topController.view.addSubview(ConfettiView(frame: topController.view.bounds)) } }) diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 1d38ee523a..c1d3c54b92 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -1522,7 +1522,7 @@ private final class PremiumIntroScreenComponent: CombinedComponent { maximumNumberOfLines: 2, lineSpacing: 0.0 ), - availableSize: context.availableSize, + availableSize: CGSize(width: context.availableSize.width - 32.0, height: context.availableSize.width), transition: context.transition ) diff --git a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift index c498faa0cc..9a9abbc3ed 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -65,8 +65,6 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { self.buttonNode.cornerRadius = 17.0 self.animationNode = DefaultAnimatedStickerNodeImpl() - self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: "Gift"), width: 384, height: 384, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - self.animationNode.visibility = true self.buttonStarsNode = PremiumStarsNode() @@ -136,11 +134,22 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { 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(_, _, durationValue): - duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(item.presentationData.strings.Notification_PremiumGift_Months(durationValue)).string + case let .giftPremium(_, _, months): + duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(item.presentationData.strings.Notification_PremiumGift_Months(months)).string + switch months { + case 12: + animationName = "Gift2" + case 6: + animationName = "Gift1" + case 3: + animationName = "Gift3" + default: + animationName = "Gift3" + } default: break } @@ -190,6 +199,10 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { return (backgroundSize.width, { boundingWidth in return (backgroundSize, { [weak self] animation, synchronousLoads, _ in if let strongSelf = self { + if strongSelf.item == nil { + strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 384, height: 384, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) + strongSelf.animationNode.visibility = true + } strongSelf.item = item strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index e75e08da6c..24ac6baf41 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -778,14 +778,16 @@ public final class WebAppController: ViewController, AttachmentContainable { self.controller?.present(alertController, in: .window(.root)) } case "web_app_setup_closing_behavior": - if let json = json, let _ = json["need_confirmation"] as? String { - + if let json = json, let needConfirmation = json["need_confirmation"] as? Bool { + self.needDismissConfirmation = needConfirmation } default: break } } + fileprivate var needDismissConfirmation = false + private var headerColorKey: String? private func updateHeaderBackgroundColor(transition: ContainedViewLayoutTransition) { let color: UIColor? @@ -1121,6 +1123,27 @@ 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 controller = textAlertController(context: self.context, title: nil, text: self.presentationData.strings.WebApp_CloseConfirmation, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.WebApp_CloseAnyway, action: { + completion() + }), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Cancel, action: { + + })], actionLayout: .vertical) + self.present(controller, in: .window(.root)) + } else { + completion() + } + } + + public func shouldDismissImmediately() -> Bool { + if self.controllerNode.needDismissConfirmation { + return false + } else { + return true + } + } } final class WebAppPickerContext: AttachmentMediaPickerContext { diff --git a/versions.json b/versions.json index 829fc8f525..c202f0582b 100644 --- a/versions.json +++ b/versions.json @@ -1,5 +1,5 @@ { - "app": "8.8.2", + "app": "8.8.3", "bazel": "5.1.0", "xcode": "13.4.1" } From c55a66eba0d49b2a142eec693ec4bb2d304788b8 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 10 Jul 2022 00:29:02 +0200 Subject: [PATCH 040/113] Various improvements --- .../Components/MediaStreamComponent.swift | 4 +- .../TelegramUI/Sources/ChatController.swift | 8 ++- .../Sources/ChatControllerInteraction.swift | 4 +- .../ChatMessageAnimatedStickerItemNode.swift | 4 +- .../Sources/ChatMessageGiftItemNode.swift | 68 ++++++++++++++++++- .../ChatRecentActionsControllerNode.swift | 2 +- .../Sources/DrawingStickersScreen.swift | 2 +- .../OverlayAudioPlayerControllerNode.swift | 2 +- .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- .../Sources/SharedAccountContext.swift | 2 +- 10 files changed, 82 insertions(+), 16 deletions(-) diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index e9992927ac..87fc1f206a 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -1197,7 +1197,7 @@ public final class MediaStreamComponentController: ViewControllerComponentContai self.view.layer.cornerCurve = .continuous } - self.view.layer.animatePosition(from: CGPoint(x: 353.0, y: 117.0), to: self.view.center, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, completion: { [weak self] _ in + 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) @@ -1247,7 +1247,7 @@ public final class MediaStreamComponentController: ViewControllerComponentContai self.view.layer.cornerCurve = .continuous } - self.view.layer.animatePosition(from: self.view.center, to: CGPoint(x: 353.0, y: 117.0), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, completion: { _ in + 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) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index a05f8bdb55..6a2b9fa3d9 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -3139,15 +3139,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 diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index 6beeb74fd9..36261570fc 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -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 @@ -225,7 +225,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, diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 240adba31b..efefbb0e54 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -423,7 +423,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 +433,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) } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift index 9a9abbc3ed..937e1b1fdc 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -40,6 +40,29 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { private var cachedMaskBackgroundImage: (CGPoint, UIImage, [CGRect])? private var absoluteRect: (CGRect, CGSize)? + private var isPlaying: Bool = false + private var wasPending: Bool = false + private var didChangeFromPendingToSent: 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 @@ -200,11 +223,19 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { return (backgroundSize, { [weak self] animation, synchronousLoads, _ in if let strongSelf = self { if strongSelf.item == nil { - strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 384, height: 384, playbackMode: .once, mode: .direct(cachePathPrefix: nil)) - strongSelf.animationNode.visibility = true + 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 + if item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal { + strongSelf.wasPending = true + } + if strongSelf.wasPending && (item.message.id.namespace != Namespaces.Message.Local && item.message.id.namespace != Namespaces.Message.ScheduledLocal) { + strongSelf.didChangeFromPendingToSent = true + } + 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) @@ -384,4 +415,37 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { return .none } } + + 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 let unreadRange = item.controllerInteraction.unreadMessageRange[UnreadMessageRangeKey(peerId: item.message.id.peerId, namespace: item.message.id.namespace)] { + if unreadRange.contains(item.message.id.id) { + if !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 { + item.controllerInteraction.animateDiceSuccess(false, true) + } + } + } } diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 936cb29704..a81534c233 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -517,7 +517,7 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode { }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 13daf942a7..0e8743ef92 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 5c6dd1e3b0..7918d25600 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 8dc1c40b17..94ba363f8b 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -2336,7 +2336,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 7f8e089a21..1d07912800 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1313,7 +1313,7 @@ public final class SharedAccountContextImpl: SharedAccountContext { }, displayPollSolution: { _, _ in }, displayPsa: { _, _ in }, displayDiceTooltip: { _ in - }, animateDiceSuccess: { _ in + }, animateDiceSuccess: { _, _ in }, displayPremiumStickerTooltip: { _, _ in }, openPeerContextMenu: { _, _, _, _, _ in }, openMessageReplies: { _, _, _ in From 028f9ff731bea4789101d65af1e873001609ff98 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 10 Jul 2022 11:04:10 +0200 Subject: [PATCH 041/113] Various fixes --- .../Sources/AttachmentContainer.swift | 2 +- .../WebUI/Sources/WebAppController.swift | 29 ++++++++++++++----- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index b4edaed71c..7ea7aecff3 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -234,7 +234,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { } } - if translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() { + if !self.isExpanded, translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() { self.cancelPanGesture() return } diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 24ac6baf41..f51919647f 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -898,7 +898,7 @@ public final class WebAppController: ViewController, AttachmentContainable { fileprivate func sendAlertButtonEvent(id: String?) { var paramsString: String? if let id = id { - paramsString = "{id: \"\(id)\"}" + paramsString = "{button_id: \"\(id)\"}" } self.webView?.sendEvent(name: "popup_closed", data: paramsString) } @@ -1013,7 +1013,9 @@ public final class WebAppController: ViewController, AttachmentContainable { if case .back = self.cancelButtonNode.state { self.controllerNode.sendBackButtonEvent() } else { - self.dismiss() + self.requestDismiss { + self.dismiss() + } } } @@ -1126,12 +1128,23 @@ public final class WebAppController: ViewController, AttachmentContainable { public func requestDismiss(completion: @escaping () -> Void) { if self.controllerNode.needDismissConfirmation { - let controller = textAlertController(context: self.context, title: nil, text: self.presentationData.strings.WebApp_CloseConfirmation, actions: [TextAlertAction(type: .genericAction, title: self.presentationData.strings.WebApp_CloseAnyway, action: { - completion() - }), TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_Cancel, action: { - - })], actionLayout: .vertical) - self.present(controller, in: .window(.root)) + 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() } From fc609c6c7076d16bd859204a89064a14f28fdcd3 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 10 Jul 2022 12:54:01 +0200 Subject: [PATCH 042/113] Various fixes --- .../SyncCore/SyncCore_Namespaces.swift | 2 +- .../Sources/NavigateToChatController.swift | 19 +++++++++++-------- .../Sources/UndoOverlayControllerNode.swift | 8 ++++---- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift index db298b43d9..acd5448e77 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -39,7 +39,7 @@ public struct Namespaces { } public struct ItemCollection { - public static let CloudStickerPacks: Int32 = 7 + public static let CloudStickerPacks: Int32 = 0 public static let CloudMaskPacks: Int32 = 1 public static let EmojiKeywords: Int32 = 2 public static let CloudAnimatedEmoji: Int32 = 3 diff --git a/submodules/TelegramUI/Sources/NavigateToChatController.swift b/submodules/TelegramUI/Sources/NavigateToChatController.swift index 4154be2ba1..826f00f043 100644 --- a/submodules/TelegramUI/Sources/NavigateToChatController.swift +++ b/submodules/TelegramUI/Sources/NavigateToChatController.swift @@ -11,6 +11,7 @@ import ChatListUI import PeerAvatarGalleryUI import SettingsUI import ChatPresentationInterfaceState +import AttachmentUI public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParams) { var found = false @@ -21,6 +22,7 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam if let updateTextInputState = params.updateTextInputState { controller.updateTextInputState(updateTextInputState) } + var popAndComplete = true if let subject = params.subject, case let .message(messageSubject, _, timecode) = subject { if case let .id(messageId) = messageSubject { let navigationController = params.navigationController @@ -33,20 +35,21 @@ public func navigateToChatControllerImpl(_ params: NavigateToChatControllerParam (navigationController?.viewControllers.last as? ViewController)?.present(c, in: .window(.root), with: a) }) } + popAndComplete = false } else if params.scrollToEndIfExists && isFirst { controller.scrollToEndOfHistory() - let _ = params.navigationController.popToViewController(controller, animated: params.animated) - params.completion(controller) } else if let search = params.activateMessageSearch { controller.activateSearch(domain: search.0, query: search.1) - let _ = params.navigationController.popToViewController(controller, animated: params.animated) - params.completion(controller) } else if let reportReason = params.reportReason { controller.beginReportSelection(reason: reportReason) - let _ = params.navigationController.popToViewController(controller, animated: params.animated) - params.completion(controller) - } else { - let _ = params.navigationController.popToViewController(controller, animated: params.animated) + } + + if popAndComplete { + if let _ = params.navigationController.viewControllers.last as? AttachmentController, let controller = params.navigationController.viewControllers[params.navigationController.viewControllers.count - 2] as? ChatControllerImpl, controller.chatLocation == params.chatLocation { + + } else { + let _ = params.navigationController.popToViewController(controller, animated: params.animated) + } params.completion(controller) } controller.purposefulAction = params.purposefulAction diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index d0bb24e117..9f9cbbb987 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -880,17 +880,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 From aa46e81a4928a22f58e9b6240b31104c01767c0a Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 10 Jul 2022 20:35:05 +0200 Subject: [PATCH 043/113] Various fixes --- .../Sources/AttachmentContainer.swift | 9 +- .../Sources/AttachmentController.swift | 15 +- .../Sources/GiftAvatarComponent.swift | 10 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 222 ++++++++---------- .../Sources/ShareControllerNode.swift | 22 +- 5 files changed, 140 insertions(+), 138 deletions(-) diff --git a/submodules/AttachmentUI/Sources/AttachmentContainer.swift b/submodules/AttachmentUI/Sources/AttachmentContainer.swift index 7ea7aecff3..bf75ed7100 100644 --- a/submodules/AttachmentUI/Sources/AttachmentContainer.swift +++ b/submodules/AttachmentUI/Sources/AttachmentContainer.swift @@ -38,6 +38,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { var controllerRemoved: ((ViewController) -> Void)? var shouldCancelPanGesture: (() -> Bool)? + var requestDismiss: (() -> Void)? var updateModalProgress: ((CGFloat, ContainedViewLayoutTransition) -> Void)? @@ -236,6 +237,7 @@ final class AttachmentContainer: ASDisplayNode, UIGestureRecognizerDelegate { if !self.isExpanded, translation > 40.0, let shouldCancelPanGesture = self.shouldCancelPanGesture, shouldCancelPanGesture() { self.cancelPanGesture() + self.requestDismiss?() return } @@ -284,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 { diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index 0d792e7619..e8bfdf2ad8 100644 --- a/submodules/AttachmentUI/Sources/AttachmentController.swift +++ b/submodules/AttachmentUI/Sources/AttachmentController.swift @@ -320,11 +320,6 @@ public class AttachmentController: ViewController { self.container.shouldCancelPanGesture = { [weak self] in if let strongSelf = self, let currentController = strongSelf.currentControllers.last { if !currentController.shouldDismissImmediately() { - currentController.requestDismiss { [weak self] in - if let strongSelf = self { - strongSelf.controller?.dismiss(animated: true) - } - } return true } else { return false @@ -334,6 +329,16 @@ public class AttachmentController: ViewController { } } + 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) diff --git a/submodules/PremiumUI/Sources/GiftAvatarComponent.swift b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift index f5fe398dd5..668a2e6a1f 100644 --- a/submodules/PremiumUI/Sources/GiftAvatarComponent.swift +++ b/submodules/PremiumUI/Sources/GiftAvatarComponent.swift @@ -50,11 +50,11 @@ private func generateDiffuseTexture() -> UIImage { class GiftAvatarComponent: Component { let context: AccountContext - let peer: EnginePeer + let peer: EnginePeer? let isVisible: Bool let hasIdleAnimations: Bool - init(context: AccountContext, peer: EnginePeer, isVisible: Bool, hasIdleAnimations: Bool) { + init(context: AccountContext, peer: EnginePeer?, isVisible: Bool, hasIdleAnimations: Bool) { self.context = context self.peer = peer self.isVisible = isVisible @@ -62,7 +62,7 @@ class GiftAvatarComponent: Component { } static func ==(lhs: GiftAvatarComponent, rhs: GiftAvatarComponent) -> Bool { - return lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations + return lhs.peer == rhs.peer && lhs.isVisible == rhs.isVisible && lhs.hasIdleAnimations == rhs.hasIdleAnimations } final class View: UIView, SCNSceneRendererDelegate, ComponentTaggedView { @@ -276,7 +276,9 @@ class GiftAvatarComponent: Component { self.hasIdleAnimations = component.hasIdleAnimations let avatarSize = CGSize(width: 100.0, height: 100.0) - self.avatarNode.setSignal(peerAvatarCompleteImage(account: component.context.account, peer: component.peer, size: avatarSize, font: avatarPlaceholderFont(size: 43.0), fullSize: true)) + 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 diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 370322e728..6fef507b35 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -500,14 +500,14 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { typealias EnvironmentType = (ViewControllerComponentContainer.Environment, ScrollChildEnvironment) let context: AccountContext - let peer: EnginePeer - let products: [InAppPurchaseManager.Product] - let selectedProductId: String + let peer: EnginePeer? + let products: [InAppPurchaseManager.Product]? + let selectedProductId: String? let present: (ViewController) -> Void let selectProduct: (String) -> Void - init(context: AccountContext, peer: EnginePeer, products: [InAppPurchaseManager.Product], selectedProductId: String, present: @escaping (ViewController) -> Void, selectProduct: @escaping (String) -> Void) { + init(context: AccountContext, peer: EnginePeer?, products: [InAppPurchaseManager.Product]?, selectedProductId: String?, present: @escaping (ViewController) -> Void, selectProduct: @escaping (String) -> Void) { self.context = context self.peer = peer self.products = products @@ -583,7 +583,6 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { let textColor = theme.list.itemPrimaryTextColor let subtitleColor = theme.list.itemSecondaryTextColor -// let arrowColor = theme.list.disclosureArrowColor let textFont = Font.regular(15.0) let boldTextFont = Font.semibold(15.0) @@ -594,7 +593,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { let text = text.update( component: MultilineTextComponent( text: .markdown( - text: strings.Premium_Gift_Description(component.peer.compactDisplayTitle).string, + text: strings.Premium_Gift_Description(component.peer?.compactDisplayTitle ?? "").string, attributes: markdownAttributes ), horizontalAlignment: .center, @@ -620,52 +619,54 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { ] var i = 0 - for product in component.products { - let monthsCount: Int - let giftTitle: String - let discount: String - switch product.id { - case "org.telegram.telegramPremium.twelveMonths": - giftTitle = strings.Premium_Gift_Years(1) - monthsCount = 12 - discount = "-15%" - case "org.telegram.telegramPremium.sixMonths": - giftTitle = strings.Premium_Gift_Months(6) - monthsCount = 6 - discount = "-10%" - case "org.telegram.telegramPremium.threeMonths": - giftTitle = strings.Premium_Gift_Months(3) - monthsCount = 3 - discount = "-7%" - default: - giftTitle = "" - monthsCount = 1 - discount = "" - } - - items.append(ProductGroupComponent.Item( - AnyComponentWithIdentity( - id: product.id, - component: AnyComponent( - GiftComponent( - title: giftTitle, - totalPrice: product.price, - perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth(monthsCount)).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 + if let products = component.products { + for product in products { + let monthsCount: Int + let giftTitle: String + let discount: String + switch product.id { + case "org.telegram.telegramPremium.twelveMonths": + giftTitle = strings.Premium_Gift_Years(1) + monthsCount = 12 + discount = "-15%" + case "org.telegram.telegramPremium.sixMonths": + giftTitle = strings.Premium_Gift_Months(6) + monthsCount = 6 + discount = "-10%" + case "org.telegram.telegramPremium.threeMonths": + giftTitle = strings.Premium_Gift_Months(3) + monthsCount = 3 + discount = "-7%" + default: + giftTitle = "" + monthsCount = 1 + discount = "" + } + + items.append(ProductGroupComponent.Item( + AnyComponentWithIdentity( + id: product.id, + component: AnyComponent( + GiftComponent( + title: giftTitle, + totalPrice: product.price, + perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth(monthsCount)).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 + ), + action: { + component.selectProduct(product.id) + }) + ) + i += 1 + } } let section = section.update( @@ -960,45 +961,43 @@ private final class PremiumGiftScreenComponent: CombinedComponent { .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0)) ) - if let peer = state.peer, let products = state.products, let selectedProductId = state.selectedProductId { - let scrollContent = scrollContent.update( - component: ScrollComponent( - content: AnyComponent(PremiumGiftScreenContentComponent( - context: context.component.context, - peer: peer, - products: products, - selectedProductId: 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) - } + 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) } - ), - 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)) - ) - } - + )), + 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 @@ -1019,23 +1018,21 @@ private final class PremiumGiftScreenComponent: CombinedComponent { titleAlpha = 1.0 } - if let peer = context.state.peer { - let star = star.update( - component: GiftAvatarComponent( - context: context.component.context, - peer: 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) - ) - } + 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)) @@ -1251,27 +1248,16 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { strongSelf.view.disablesInteractiveModalDismiss = inProgress } } - -// presentImpl = { [weak self] c in -// self?.present(c, in: .window(.root)) -// } - + pushImpl = { [weak self] c in self?.push(c) } completionImpl = { [weak self] duration in if let strongSelf = self, let navigationController = strongSelf.navigationController as? NavigationController { -// let introController = PremiumIntroScreen(context: context, source: .gift(from: context.account.peerId, to: peerId, duration: duration)) var controllers = navigationController.viewControllers controllers = controllers.filter { !($0 is PeerInfoScreen) && !($0 is PremiumGiftScreen) } navigationController.setViewControllers(controllers, animated: true) - - Queue.mainQueue().after(2.8, { - if let topController = navigationController.viewControllers.last { - topController.view.addSubview(ConfettiView(frame: topController.view.bounds)) - } - }) } } } 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) From c51b58ca728ec6abca3413be381afdc9bc107238 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 01:21:54 +0200 Subject: [PATCH 044/113] [WIP] Entity input panel --- .../Telegram-iOS/en.lproj/Localizable.strings | 6 + .../Sources/AccountContext.swift | 7 +- .../Sources/ChatListController.swift | 2 +- .../Sources/ChatListSearchContainerNode.swift | 2 +- .../Sources/Node/ChatListItem.swift | 3 +- .../Source/Base/Transition.swift | 140 +++- .../Source/Components/Button.swift | 4 +- .../Source/Host/ComponentHostView.swift | 3 - .../Sources/LottieAnimationComponent.swift | 21 +- .../Sources/PagerComponent.swift | 23 +- .../Sources/ContactsControllerNode.swift | 2 +- .../ContextUI/Sources/ContextController.swift | 30 +- .../ContainedViewLayoutTransition.swift | 4 +- .../Source/ContextContentSourceNode.swift | 6 +- .../Source/ContextControllerSourceNode.swift | 2 +- submodules/Display/Source/TextNode.swift | 9 +- .../Sources/ListMessageSnippetItemNode.swift | 6 + .../Sources/PeersNearbyController.swift | 2 +- .../ArchivedStickerPacksController.swift | 3 + .../InstalledStickerPacksController.swift | 77 +- .../Sources/ThemePickerController.swift | 2 +- .../Themes/ThemeSettingsController.swift | 2 +- .../StickerPackPreviewControllerNode.swift | 4 + .../Sources/StickerPackScreen.swift | 4 + .../Components/MediaStreamComponent.swift | 2 +- .../Sources/Account/Account.swift | 1 + .../Network/FetchedMediaResource.swift | 55 +- .../State/AccountStateManagementUtils.swift | 16 + ...onizeInstalledStickerPacksOperations.swift | 12 +- .../Sources/State/StickerManagement.swift | 1 + ...ronizeInstalledStickerPacksOperation.swift | 5 + .../SyncCore/SyncCore_MediaReference.swift | 29 + .../SyncCore/SyncCore_Namespaces.swift | 2 + .../SyncCore_StickerPackCollectionInfo.swift | 4 + ...onizeInstalledStickerPacksOperations.swift | 1 + .../SyncCore/SyncCore_TelegramMediaFile.swift | 34 + .../Peers/UpdateCachedPeerData.swift | 2 + .../Stickers/ArchivedStickerPacks.swift | 5 + .../Stickers/CachedStickerPack.swift | 2 +- .../Stickers/ImportStickers.swift | 2 + .../Stickers/LoadedStickerPack.swift | 2 + .../TelegramEngine/Stickers/StickerPack.swift | 3 + .../StickerPackInteractiveOperations.swift | 4 + .../Resources/PresentationResourceKey.swift | 1 + .../Resources/PresentationResourcesChat.swift | 6 + .../Sources/EmojiTextAttachmentView.swift | 32 +- .../Components/EntityKeyboard/BUILD | 2 + .../Sources/EmojiPagerContentComponent.swift | 714 ++++++++++++---- .../Sources/EntityKeyboard.swift | 161 +++- ...tyKeyboardTopContainerPanelComponent.swift | 19 +- .../EntityKeyboardTopPanelComponent.swift | 761 ++++++++++++++++- .../Sources/GifPagerContentComponent.swift | 53 +- .../Sources/LottieAnimationCache.swift | 6 + .../Components/MultiAnimationRenderer/BUILD | 43 + .../MultiAnimationRendererShaders.metal | 38 + .../Sources/MultiAnimationMetalRenderer.swift | 767 ++++++++++++++++++ .../Sources/MultiAnimationRenderer.swift | 45 +- .../Sources/TextNodeWithEntities.swift | 13 +- .../Animations/emojicat_activity.json | 1 + .../Animations/emojicat_animals.json | 1 + .../Resources/Animations/emojicat_flags.json | 1 + .../Resources/Animations/emojicat_food.json | 1 + .../Animations/emojicat_objects.json | 1 + .../Resources/Animations/emojicat_places.json | 1 + .../Resources/Animations/emojicat_smiles.json | 1 + .../Animations/emojicat_symbols.json | 1 + submodules/TelegramUI/Resources/emoji1016.txt | 15 + .../TelegramUI/Sources/ChatController.swift | 10 +- .../Sources/ChatControllerNode.swift | 8 +- .../Sources/ChatEntityKeyboardInputNode.swift | 416 ++++++++-- .../Sources/ChatMediaInputNode.swift | 10 +- .../Sources/ChatMessageActionItemNode.swift | 3 +- .../ChatMessageAnimatedStickerItemNode.swift | 6 +- .../Sources/ChatMessageBubbleItemNode.swift | 20 +- .../ChatMessageInstantVideoItemNode.swift | 6 +- .../Sources/ChatMessageReplyInfoNode.swift | 6 +- .../Sources/ChatMessageStickerItemNode.swift | 6 +- .../ChatMessageTextBubbleContentNode.swift | 8 +- .../ChatPinnedMessageTitlePanelNode.swift | 3 +- .../ChatRecentActionsControllerNode.swift | 3 +- .../ChatSearchResultsContollerNode.swift | 2 +- .../Sources/ChatTextInputPanelNode.swift | 5 + .../Sources/FeaturedStickersScreen.swift | 8 +- ...rizontalStickersChatContextPanelNode.swift | 4 +- .../Sources/InlineReactionSearchPanel.swift | 4 +- .../TelegramUI/Sources/OpenResolvedUrl.swift | 2 +- submodules/TelegramUI/Sources/OpenUrl.swift | 16 + .../Sources/PeerInfo/PeerInfoScreen.swift | 2 +- .../Sources/ReplyAccessoryPanelNode.swift | 3 +- .../StickersChatInputContextPanelNode.swift | 4 +- .../TelegramUI/Sources/TextLinkHandling.swift | 8 +- .../Sources/UndoOverlayController.swift | 2 +- .../Sources/UndoOverlayControllerNode.swift | 13 +- .../UrlHandling/Sources/UrlHandling.swift | 14 +- .../MetalWallpaperBackgroundNode.swift | 1 + .../CoreAnimation/CoreAnimationLayer.swift | 4 + .../MainThreadAnimationLayer.swift | 8 + .../Sources/Private/RootAnimationLayer.swift | 1 + .../AnimationKeypathExtension.swift | 23 + .../Public/Animation/AnimationView.swift | 4 + .../DynamicProperties/AnimationKeypath.swift | 2 +- 101 files changed, 3374 insertions(+), 491 deletions(-) create mode 100644 submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal create mode 100644 submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_activity.json create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_animals.json create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_flags.json create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_food.json create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_objects.json create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_places.json create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_smiles.json create mode 100644 submodules/TelegramUI/Resources/Animations/emojicat_symbols.json create mode 100644 submodules/TelegramUI/Resources/emoji1016.txt diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index f9142b2715..367d872258 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7834,3 +7834,9 @@ Sorry for the inconvenience."; "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"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index f19aa57c43..aa44f81472 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) diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 8cd265b4c0..539cf35828 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 } diff --git a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift index 36c6fe2a12..000eeaa071 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchContainerNode.swift @@ -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/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index 6a797147fa..ab5dcb5491 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -1801,7 +1801,8 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { context: item.context, cache: item.interaction.animationCache, renderer: item.interaction.animationRenderer, - placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor + placeholderColor: item.presentationData.theme.list.mediaPlaceholderColor, + attemptSynchronous: synchronousLoads )) let _ = authorApply() diff --git a/submodules/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index 363a67f497..c21d1afcf7 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -53,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) @@ -88,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 { @@ -225,6 +227,36 @@ public struct Transition { } } + 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)) + } + } + public func setBounds(view: UIView, bounds: CGRect, completion: ((Bool) -> Void)? = nil) { if view.bounds == bounds { completion?(true) @@ -454,6 +486,10 @@ public struct Transition { 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: @@ -491,4 +527,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 27f749aa5f..1332bd0af0 100644 --- a/submodules/ComponentFlow/Source/Components/Button.swift +++ b/submodules/ComponentFlow/Source/Components/Button.swift @@ -154,7 +154,7 @@ public final class Button: Component { self.holdActionTimer?.invalidate() if #available(iOS 10.0, *) { - let holdActionTimer = Timer(timeInterval: 1.0, repeats: false, block: { [weak self] _ in + let holdActionTimer = Timer(timeInterval: 0.5, repeats: false, block: { [weak self] _ in guard let strongSelf = self else { return } @@ -173,7 +173,7 @@ public final class Button: Component { private func beginExecuteHoldActionTimer() { self.holdActionTimer?.invalidate() if #available(iOS 10.0, *) { - let holdActionTimer = Timer(timeInterval: 0.2, repeats: true, block: { [weak self] _ in + let holdActionTimer = Timer(timeInterval: 0.1, repeats: true, block: { [weak self] _ in guard let strongSelf = self else { return } diff --git a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift index e5407341f4..ec1ae334f0 100644 --- a/submodules/ComponentFlow/Source/Host/ComponentHostView.swift +++ b/submodules/ComponentFlow/Source/Host/ComponentHostView.swift @@ -203,9 +203,6 @@ public final class ComponentView { } let updatedSize = component._update(view: componentView, availableSize: containerSize, environment: context.erasedEnvironment, transition: transition) - if transition.userData(ComponentHostViewSkipSettingFrame.self) == nil { - transition.setFrame(view: componentView, frame: CGRect(origin: CGPoint(), size: updatedSize)) - } if isEnvironmentUpdated { context.erasedEnvironment._isUpdated = false diff --git a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift index cad54a967a..8c773c16df 100644 --- a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift +++ b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift @@ -7,8 +7,13 @@ 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 } @@ -153,7 +158,11 @@ public final class LottieAnimationComponent: Component { view.backgroundColor = .clear view.isOpaque = false - //view.logHierarchyKeypaths() + if let value = component.animation.colors["__allcolors__"] { + for keypath in view.allKeypaths(predicate: { $0.keys.last == "Color" }) { + view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: keypath)) + } + } for (key, value) in component.animation.colors { view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color")) @@ -188,6 +197,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/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index a122249858..aa06aec2fa 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -298,6 +298,8 @@ public final class PagerComponent (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 } diff --git a/submodules/Display/Source/ContainedViewLayoutTransition.swift b/submodules/Display/Source/ContainedViewLayoutTransition.swift index 15fea6c105..32da03d32b 100644 --- a/submodules/Display/Source/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Source/ContainedViewLayoutTransition.swift @@ -625,8 +625,8 @@ public extension ContainedViewLayoutTransition { } else { switch self { case .immediate: - view.layer.removeAnimation(forKey: "position") - view.layer.removeAnimation(forKey: "bounds") + //view.layer.removeAnimation(forKey: "position") + //view.layer.removeAnimation(forKey: "bounds") view.frame = frame 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 3e2d8916c5..0bfd0ce673 100644 --- a/submodules/Display/Source/ContextControllerSourceNode.swift +++ b/submodules/Display/Source/ContextControllerSourceNode.swift @@ -271,7 +271,7 @@ open class ContextControllerSourceView: UIView { public weak var additionalActivationProgressLayer: CALayer? public var targetNodeForActivationProgress: ASDisplayNode? public var targetViewForActivationProgress: UIView? - public var targetLayerForActivationProgress: CALayer? + public weak var targetLayerForActivationProgress: CALayer? public var targetNodeForActivationProgressContentRect: CGRect? public var useSublayerTransformForActivation: Bool = true diff --git a/submodules/Display/Source/TextNode.swift b/submodules/Display/Source/TextNode.swift index 8231bad342..d77115e99d 100644 --- a/submodules/Display/Source/TextNode.swift +++ b/submodules/Display/Source/TextNode.swift @@ -1126,6 +1126,10 @@ open class TextNode: ASDisplayNode { rightOffset = ceil(secondaryRightOffset) } + if embeddedItems.count > 25 { + assert(true) + } + embeddedItems.append(TextNodeEmbeddedItem(range: NSMakeRange(startIndex, endIndex - startIndex + 1), frame: CGRect(x: min(leftOffset, rightOffset), y: descent - (ascent + descent), width: abs(rightOffset - leftOffset) + rightInset, height: ascent + descent), item: item)) } @@ -1136,6 +1140,9 @@ open class TextNode: ASDisplayNode { isLastLine = true } if isLastLine { + if attributedString.string.hasPrefix("😀") { + assert(true) + } if first { first = false } else { @@ -1175,7 +1182,7 @@ open 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 } } 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[.. 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,9 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati } entries.append(.masks(presentationData.theme, presentationData.strings.MaskStickerSettings_Title)) + //TODO:localize + entries.append(.emoji(presentationData.theme, "Emoji")) + entries.append(.quickReaction(presentationData.strings.Settings_QuickReactionSetup_NavigationTitle, quickReactionImage)) entries.append(.animatedStickers(presentationData.theme, presentationData.strings.StickerPacksSettings_AnimatedStickers, stickerSettings.loopAnimatedStickers)) @@ -576,6 +603,11 @@ 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 { + //TODO:localize + entries.append(.archived(presentationData.theme, "Archived Emoji", Int32(archived.count), archived)) + } } if let stickerPacksView = view.views[.itemCollectionInfos(namespaces: [namespaceForMode(mode)])] as? ItemCollectionInfosView { @@ -618,6 +650,9 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati markdownString = presentationData.strings.StickerPacksSettings_ManagingHelp case .masks: markdownString = presentationData.strings.MaskStickerSettings_Info + case .emoji: + //TODO:localize + markdownString = "Emoji" } let entities = generateTextEntities(markdownString, enabledTypes: [.mention]) if let entity = entities.first { @@ -633,6 +668,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 { @@ -731,6 +767,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 +780,8 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta switch mode { case .masks: archivedMode = .masks + case .emoji: + archivedMode = .emoji default: archivedMode = .stickers } @@ -876,6 +916,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 +1071,9 @@ public func installedStickerPacksController(context: AccountContext, mode: Insta title = presentationData.strings.StickerPacksSettings_Title case .masks: title = presentationData.strings.MaskStickerSettings_Title + case .emoji: + //TODO:localize + title = "Emoji" } let controllerState = ItemListControllerState(presentationData: ItemListPresentationData(presentationData), title: .text(title), leftNavigationButton: leftNavigationButton, rightNavigationButton: rightNavigationButton, backNavigationButton: ItemListBackButton(title: presentationData.strings.Common_Back), animateChanges: true) 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/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/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift index d17a2d11ba..8aefdfae14 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewControllerNode.swift @@ -620,6 +620,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 +630,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/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 8ce32224e7..7a8e8ce58d 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -701,6 +701,8 @@ private final class StickerPackContainer: ASDisplayNode { 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(entries.count)) } else { text = self.presentationData.strings.StickerPack_RemoveMaskCount(Int32(entries.count)) } @@ -710,6 +712,8 @@ private final class StickerPackContainer: ASDisplayNode { 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(entries.count)) } else { text = self.presentationData.strings.StickerPack_AddMaskCount(Int32(entries.count)) } diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index 930de2caa4..399eda693e 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -805,7 +805,7 @@ public final class MediaStreamComponent: CombinedComponent { "Point 3.Group 1.Fill 1": whiteColor, "Point 1.Group 1.Fill 1": whiteColor ], - mode: .still + mode: .still(position: .begin) ), size: CGSize(width: 22.0, height: 22.0) ).tagged(moreAnimationTag))), 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/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/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index 73fa894fba..cd37a30e9d 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 } @@ -3459,9 +3461,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): @@ -3501,6 +3505,8 @@ func replayFinalState( 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 +3518,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 +3540,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 +3550,8 @@ func replayFinalState( syncStickers = true case .masks: syncMasks = true + case .emoji: + syncEmoji = true } } else { var currentDict: [ItemCollectionId: StickerPackCollectionInfo] = [:] @@ -3556,6 +3568,7 @@ func replayFinalState( case .sync: syncStickers = true syncMasks = true + syncEmoji = true break loop } } @@ -3565,6 +3578,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/ManagedSynchronizeInstalledStickerPacksOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift index 1b73b655f3..bd5ca0c408 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) @@ -295,6 +297,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 +316,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 +441,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 +454,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/StickerManagement.swift b/submodules/TelegramCore/Sources/State/StickerManagement.swift index 3b17917a19..6ed01b4b11 100644 --- a/submodules/TelegramCore/Sources/State/StickerManagement.swift +++ b/submodules/TelegramCore/Sources/State/StickerManagement.swift @@ -17,6 +17,7 @@ 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) 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/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 db298b43d9..44b31cdbc4 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -46,6 +46,7 @@ public struct Namespaces { public static let CloudDice: Int32 = 4 public static let CloudAnimatedEmojiAnimations: Int32 = 5 public static let CloudAnimatedEmojiReactions: Int32 = 6 + public static let CloudEmojiPacks: Int32 = 8 } public struct OrderedItemList { @@ -164,6 +165,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_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_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index df9fbc310d..e69d9f2550 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -590,6 +590,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/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index a8f0eb91ea..043ec2659c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -544,6 +544,8 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee 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/ArchivedStickerPacks.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ArchivedStickerPacks.swift index bbd76d3042..e9743b26ee 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ArchivedStickerPacks.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ArchivedStickerPacks.swift @@ -7,6 +7,7 @@ import SwiftSignalKit public enum ArchivedStickerPacksNamespace: Int32 { case stickers = 0 case masks = 1 + case emoji = 2 var itemCollectionNamespace: ItemCollectionId.Namespace { switch self { @@ -14,6 +15,8 @@ public enum ArchivedStickerPacksNamespace: Int32 { return Namespaces.ItemCollection.CloudStickerPacks case .masks: return Namespaces.ItemCollection.CloudMaskPacks + case .emoji: + return Namespaces.ItemCollection.CloudEmojiPacks } } } @@ -32,6 +35,8 @@ func _internal_archivedStickerPacks(account: Account, namespace: ArchivedSticker var flags: Int32 = 0 if case .masks = namespace { flags |= 1 << 0 + } else if case .emoji = namespace { + flags |= 1 << 1 } return account.network.request(Api.functions.messages.getArchivedStickers(flags: flags, offsetId: 0, limit: 200)) |> map { result -> [ArchivedStickerPackItem] in diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift index 8c71c80536..3e475f6888 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/CachedStickerPack.swift @@ -154,7 +154,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 { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift index 3331fa05b5..36f1f53365 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift @@ -173,6 +173,8 @@ func _internal_createStickerSet(account: Account, title: String, shortName: Stri 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/LoadedStickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift index 0abcc50461..0aad8c5696 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift @@ -52,6 +52,8 @@ func updatedRemoteStickerPack(postbox: Postbox, network: Network, reference: Sti 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/StickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift index eecdae4f7b..556bd90a04 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift @@ -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? diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift index 4c40991bdd..46562bcf55 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift @@ -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 } @@ -57,6 +59,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/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index da1c28b02e..a8174639c5 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -276,6 +276,7 @@ public enum PresentationResourceKey: Int32 { case chatKeyboardActionButtonProfileIcon case chatKeyboardActionButtonAddToChatIcon case chatKeyboardActionButtonWebAppIcon + case chatEntityKeyboardLock case uploadToneIcon } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index e569f326f5..e7e93439fb 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -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) -> UIImage? { + return theme.image(PresentationResourceKey.chatEntityKeyboardLock.rawValue, { theme in + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/SmallLock"), color: theme.chat.inputMediaPanel.stickersSectionTextColor) + }) + } } diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index 2a534c0b22..e22da66af9 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -69,7 +69,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { super.init() if let file = file { - self.updateFile(file: file, attemptSynchronousLoad: true) + self.updateFile(file: file, attemptSynchronousLoad: attemptSynchronousLoad) } else { self.infoDisposable = (context.engine.stickers.resolveInlineSticker(fileId: emoji.fileId) |> deliverOnMainQueue).start(next: { [weak self] file in @@ -130,10 +130,30 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { self.loadAnimation() } else { - self.loadDisposable = self.renderer.loadFirstFrame(groupId: self.groupId, target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, completion: { [weak self] _ in - self?.loadAnimation() + let pointSize = self.pointSize + let placeholderColor = self.placeholderColor + self.loadDisposable = self.renderer.loadFirstFrame(groupId: self.groupId, 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, 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.loadAnimation() + } + } + } else { + guard let strongSelf = self else { + return + } + strongSelf.loadAnimation() + } }) - self.loadAnimation() } } @@ -151,7 +171,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { return } - if file.isVideoSticker { + 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 { @@ -162,7 +182,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } }) - let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: file.resource).start() + let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: .customEmoji(media: file), resource: file.resource).start() return ActionDisposable { dataDisposable.dispose() diff --git a/submodules/TelegramUI/Components/EntityKeyboard/BUILD b/submodules/TelegramUI/Components/EntityKeyboard/BUILD index 353a3fa407..49ea2ba2bc 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/BUILD +++ b/submodules/TelegramUI/Components/EntityKeyboard/BUILD @@ -39,6 +39,8 @@ swift_library( "//submodules/StickerPackPreviewUI:StickerPackPreviewUI", "//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 index 37500a96b5..09fd0b9db5 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -22,6 +22,8 @@ import ContextUI import PremiumUI import StickerPackPreviewUI import UndoUI +import AudioToolbox +import SolidRoundedButtonComponent private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bundleImageName: "Chat List/PeerPremiumIcon"), color: .white) @@ -52,6 +54,74 @@ private final class PremiumBadgeView: UIView { } } +private final class GroupHeaderLayer: SimpleLayer { + private var lockIconLayer: SimpleLayer? + + private var currentTextLayout: (string: String, color: UIColor, constrainedWidth: CGFloat, size: CGSize)? + + override init() { + super.init() + } + + override init(layer: Any) { + super.init(layer: layer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(theme: PresentationTheme, title: String, isPremium: Bool, constrainedWidth: CGFloat) -> (size: CGSize, horizontalOffset: CGFloat) { + let color = theme.chat.inputMediaPanel.stickersSectionTextColor + + let horizontalOffset: CGFloat + if isPremium { + let lockIconLayer: SimpleLayer + if let current = self.lockIconLayer { + lockIconLayer = current + } else { + lockIconLayer = SimpleLayer() + self.lockIconLayer = lockIconLayer + self.addSublayer(lockIconLayer) + } + if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme) { + let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0)) + lockIconLayer.contents = image.cgImage + horizontalOffset = imageSize.width + 2.0 + lockIconLayer.frame = CGRect(origin: CGPoint(x: -imageSize.width - 2.0, y: 0.0), size: imageSize) + } else { + lockIconLayer.contents = nil + horizontalOffset = 0.0 + } + } else { + if let lockIconLayer = self.lockIconLayer { + self.lockIconLayer = nil + lockIconLayer.removeFromSuperlayer() + } + horizontalOffset = 0.0 + } + + if let currentTextLayout = self.currentTextLayout, currentTextLayout.string == title, currentTextLayout.color == color, currentTextLayout.constrainedWidth == constrainedWidth { + return (currentTextLayout.size, horizontalOffset) + } + + let string = NSAttributedString(string: title.uppercased(), font: Font.medium(12.0), textColor: color) + let stringBounds = string.boundingRect(with: CGSize(width: constrainedWidth, height: 100.0), options: .usesLineFragmentOrigin, context: nil) + let size = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height)) + self.contents = generateImage(size, 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, constrainedWidth, size) + + return (size, horizontalOffset) + } +} + public final class EmojiPagerContentComponent: Component { public typealias EnvironmentType = (EntityKeyboardChildEnvironment, PagerComponentChildEnvironment) @@ -59,6 +129,7 @@ public final class EmojiPagerContentComponent: Component { public let performItemAction: (Item, UIView, CGRect, CALayer) -> Void public let deleteBackwards: () -> Void public let openStickerSettings: () -> Void + public let openPremiumSection: () -> Void public let pushController: (ViewController) -> Void public let presentController: (ViewController) -> Void public let presentGlobalOverlayController: (ViewController) -> Void @@ -70,6 +141,7 @@ public final class EmojiPagerContentComponent: Component { performItemAction: @escaping (Item, UIView, CGRect, CALayer) -> Void, deleteBackwards: @escaping () -> Void, openStickerSettings: @escaping () -> Void, + openPremiumSection: @escaping () -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController) -> Void, presentGlobalOverlayController: @escaping (ViewController) -> Void, @@ -80,6 +152,7 @@ public final class EmojiPagerContentComponent: Component { self.performItemAction = performItemAction self.deleteBackwards = deleteBackwards self.openStickerSettings = openStickerSettings + self.openPremiumSection = openPremiumSection self.pushController = pushController self.presentController = presentController self.presentGlobalOverlayController = presentGlobalOverlayController @@ -89,28 +162,43 @@ public final class EmojiPagerContentComponent: Component { } } + 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 emoji: String - public let file: TelegramMediaFile - public let stickerPackItem: StickerPackItem? + public let file: TelegramMediaFile? + public let staticEmoji: String? + public let subgroupId: Int32? - public init(emoji: String, file: TelegramMediaFile, stickerPackItem: StickerPackItem?) { - self.emoji = emoji + public init( + file: TelegramMediaFile?, + staticEmoji: String?, + subgroupId: Int32? + ) { self.file = file - self.stickerPackItem = stickerPackItem + self.staticEmoji = staticEmoji + self.subgroupId = subgroupId } public static func ==(lhs: Item, rhs: Item) -> Bool { if lhs === rhs { return true } - if lhs.emoji != rhs.emoji { + if lhs.file?.fileId != rhs.file?.fileId { return false } - if lhs.file.fileId != rhs.file.fileId { + if lhs.staticEmoji != rhs.staticEmoji { return false } - if lhs.stickerPackItem?.file.fileId != rhs.stickerPackItem?.file.fileId { + if lhs.subgroupId != rhs.subgroupId { return false } @@ -119,27 +207,45 @@ public final class EmojiPagerContentComponent: Component { } public final class ItemGroup: Equatable { - public let id: AnyHashable + public let supergroupId: AnyHashable + public let groupId: AnyHashable public let title: String? + public let isPremium: Bool + public let displayPremiumBadges: Bool public let items: [Item] public init( - id: AnyHashable, + supergroupId: AnyHashable, + groupId: AnyHashable, title: String?, + isPremium: Bool, + displayPremiumBadges: Bool, items: [Item] ) { - self.id = id + self.supergroupId = supergroupId + self.groupId = groupId self.title = title + self.isPremium = isPremium + self.displayPremiumBadges = displayPremiumBadges self.items = items } public static func ==(lhs: ItemGroup, rhs: ItemGroup) -> Bool { - if lhs.id != rhs.id { + if lhs.supergroupId != rhs.supergroupId { + return false + } + if lhs.groupId != rhs.groupId { return false } if lhs.title != rhs.title { return false } + if lhs.isPremium != rhs.isPremium { + return false + } + if lhs.displayPremiumBadges != rhs.displayPremiumBadges { + return false + } if lhs.items != rhs.items { return false } @@ -214,14 +320,17 @@ public final class EmojiPagerContentComponent: Component { public final class View: UIView, UIScrollViewDelegate, ComponentTaggedView { private struct ItemGroupDescription: Equatable { - let id: AnyHashable + let supergroupId: AnyHashable + let groupId: AnyHashable let hasTitle: Bool + let isPremium: Bool let itemCount: Int } private struct ItemGroupLayout: Equatable { let frame: CGRect - let id: AnyHashable + let supergroupId: AnyHashable + let groupId: AnyHashable let itemTopOffset: CGFloat let itemCount: Int } @@ -238,10 +347,16 @@ public final class EmojiPagerContentComponent: Component { var itemsPerRow: Int var contentSize: CGSize - init(width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], itemLayoutType: ItemLayoutType) { + var premiumButtonInset: CGFloat + var premiumButtonHeight: CGFloat + + init(width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], itemLayoutType: ItemLayoutType, expandedPremiumGroups: Set) { self.width = width self.containerInsets = containerInsets + self.premiumButtonInset = 6.0 + self.premiumButtonHeight = 50.0 + let minItemsPerRow: Int let minSpacing: CGFloat switch itemLayoutType { @@ -276,10 +391,14 @@ public final class EmojiPagerContentComponent: Component { } let numRowsInGroup = (itemGroup.itemCount + (self.itemsPerRow - 1)) / self.itemsPerRow - let groupContentSize = CGSize(width: width, height: itemTopOffset + CGFloat(numRowsInGroup) * self.visibleItemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) + var groupContentSize = CGSize(width: width, height: itemTopOffset + CGFloat(numRowsInGroup) * self.visibleItemSize + CGFloat(max(0, numRowsInGroup - 1)) * self.verticalSpacing) + if itemGroup.isPremium && expandedPremiumGroups.contains(itemGroup.groupId) { + groupContentSize.height += self.premiumButtonInset + self.premiumButtonHeight + } self.itemGroupLayouts.append(ItemGroupLayout( frame: CGRect(origin: CGPoint(x: 0.0, y: verticalGroupOrigin), size: groupContentSize), - id: itemGroup.id, + supergroupId: itemGroup.supergroupId, + groupId: itemGroup.groupId, itemTopOffset: itemTopOffset, itemCount: itemGroup.itemCount )) @@ -307,8 +426,8 @@ public final class EmojiPagerContentComponent: Component { ) } - func visibleItems(for rect: CGRect) -> [(id: AnyHashable, groupIndex: Int, groupItems: Range)] { - var result: [(id: AnyHashable, groupIndex: Int, groupItems: Range)] = [] + 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] @@ -326,7 +445,8 @@ public final class EmojiPagerContentComponent: Component { if maxVisibleIndex >= minVisibleIndex { result.append(( - id: group.id, + supergroupId: group.supergroupId, + groupId: group.groupId, groupIndex: groupIndex, groupItems: minVisibleIndex ..< (maxVisibleIndex + 1) )) @@ -394,12 +514,14 @@ public final class EmojiPagerContentComponent: Component { final class ItemLayer: MultiAnimationRenderTarget { struct Key: Hashable { var groupId: AnyHashable - var fileId: MediaId + var fileId: MediaId? + var staticEmoji: String? } let item: Item - private let file: TelegramMediaFile + private let file: TelegramMediaFile? + private let staticEmoji: String? private let placeholderColor: UIColor private let size: CGSize private var disposable: Disposable? @@ -422,7 +544,8 @@ public final class EmojiPagerContentComponent: Component { context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, - file: TelegramMediaFile, + file: TelegramMediaFile?, + staticEmoji: String?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, @@ -433,6 +556,7 @@ public final class EmojiPagerContentComponent: Component { ) { self.item = item self.file = file + self.staticEmoji = staticEmoji self.placeholderColor = placeholderColor self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder @@ -442,86 +566,107 @@ public final class EmojiPagerContentComponent: Component { super.init() - if file.isAnimatedSticker || file.isVideoSticker { - let loadAnimation: () -> Void = { [weak self] in - guard let strongSelf = self else { - return - } - - strongSelf.disposable = renderer.add(groupId: groupId, 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) + if let file = file { + if file.isAnimatedSticker || file.isVideoEmoji { + let loadAnimation: () -> Void = { [weak self] in + guard let strongSelf = self else { + return + } - let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in - guard let result = result else { - return - } + strongSelf.disposable = renderer.add(groupId: groupId, 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) - if file.isVideoSticker { - 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() + let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in + guard let result = result else { return } - cacheLottieAnimation(data: data, width: Int(size.width), height: Int(size.height), writer: writer) + + if file.isVideoEmoji { + 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() } }) - - let fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: file.resource).start() - - return ActionDisposable { - dataDisposable.dispose() - fetchDisposable.dispose() - } - }) - } - - if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { - self.updateDisplayPlaceholder(displayPlaceholder: true) } - loadAnimation() - } else { - let _ = renderer.loadFirstFrame(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { [weak self] success in + if attemptSynchronousLoad { + if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { + self.updateDisplayPlaceholder(displayPlaceholder: true) + } + loadAnimation() - - if !success { - guard let strongSelf = self else { - return - } + } else { + let _ = renderer.loadFirstFrame(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { [weak self] success in + loadAnimation() - strongSelf.updateDisplayPlaceholder(displayPlaceholder: true) + if !success { + guard let strongSelf = self else { + return + } + + strongSelf.updateDisplayPlaceholder(displayPlaceholder: true) + } + }) + } + } else if let dimensions = file.dimensions { + let isSmall: Bool = false + self.disposable = (chatMessageSticker(account: context.account, file: file, small: isSmall, synchronousLoad: attemptSynchronousLoad)).start(next: { [weak self] resultTransform in + let boundingSize = CGSize(width: 93.0, height: 93.0) + let imageSize = dimensions.cgSize.aspectFilled(boundingSize) + + if let image = resultTransform(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .fill(.clear)))?.generateImage() { + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + + strongSelf.contents = image.cgImage + } } }) - } - } else if let dimensions = file.dimensions { - let isSmall: Bool = false - self.disposable = (chatMessageSticker(account: context.account, file: file, small: isSmall, synchronousLoad: attemptSynchronousLoad)).start(next: { [weak self] resultTransform in - let boundingSize = CGSize(width: 93.0, height: 93.0) - let imageSize = dimensions.cgSize.aspectFilled(boundingSize) - if let image = resultTransform(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .fill(.clear)))?.generateImage() { - Queue.mainQueue().async { - guard let strongSelf = self else { - return - } - - strongSelf.contents = image.cgImage - } - } - }) + self.fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: isSmall)).start() + } - self.fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: isSmall)).start() - } - - if displayPremiumBadgeIfAvailable && file.isPremiumSticker { - let premiumBadgeView = PremiumBadgeView() - let badgeSize = CGSize(width: 20.0, height: 20.0) - premiumBadgeView.frame = CGRect(origin: CGPoint(x: pointSize.width - badgeSize.width, y: pointSize.height - badgeSize.height), size: badgeSize) - premiumBadgeView.update(backgroundColor: blurredBadgeColor, size: badgeSize) - self.premiumBadgeView = premiumBadgeView - self.addSublayer(premiumBadgeView.layer) + if displayPremiumBadgeIfAvailable && file.isPremiumSticker { + let premiumBadgeView = PremiumBadgeView() + let badgeSize = CGSize(width: 20.0, height: 20.0) + premiumBadgeView.frame = CGRect(origin: CGPoint(x: pointSize.width - badgeSize.width, y: pointSize.height - badgeSize.height), size: badgeSize) + premiumBadgeView.update(backgroundColor: blurredBadgeColor, size: badgeSize) + self.premiumBadgeView = premiumBadgeView + self.addSublayer(premiumBadgeView.layer) + } + } 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.3 + 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(30.0 * scaleFactor)), textColor: .black) + let boundingRect = string.boundingRect(with: scaledSize, options: .usesLineFragmentOrigin, context: nil) + UIGraphicsPushContext(context) + string.draw(at: CGPoint(x: (scaledSize.width - boundingRect.width) / 2.0 + boundingRect.minX, y: (scaledSize.height - boundingRect.height) / 2.0 + boundingRect.minY)) + UIGraphicsPopContext() + }) + self.contents = image?.cgImage } } @@ -533,6 +678,7 @@ public final class EmojiPagerContentComponent: Component { self.item = layer.item self.file = layer.file + self.staticEmoji = layer.staticEmoji self.placeholderColor = layer.placeholderColor self.size = layer.size @@ -616,6 +762,24 @@ public final class EmojiPagerContentComponent: Component { } } + private final class GroupBorderLayer: CAShapeLayer { + override func action(forKey event: String) -> CAAction? { + return nullAction + } + + override init() { + super.init() + } + + override init(layer: Any) { + super.init(layer: layer) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + } + private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { } @@ -628,18 +792,22 @@ public final class EmojiPagerContentComponent: Component { private var visibleItemPlaceholderViews: [ItemLayer.Key: ItemPlaceholderView] = [:] private var visibleItemLayers: [ItemLayer.Key: ItemLayer] = [:] - private var visibleGroupHeaders: [AnyHashable: ComponentView] = [:] + private var visibleGroupHeaders: [AnyHashable: GroupHeaderLayer] = [:] + private var visibleGroupBorders: [AnyHashable: GroupBorderLayer] = [:] + private var visibleGroupPremiumButtons: [AnyHashable: ComponentView] = [:] + private var expandedPremiumGroups: 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 theme: PresentationTheme? private var activeItemUpdated: ActionSlot<(AnyHashable, Transition)>? private var itemLayout: ItemLayout? + private var peekRecognizer: PeekControllerGestureRecognizer? private var currentContextGestureItemKey: ItemLayer.Key? - private weak var peekController: PeekController? override init(frame: CGRect) { @@ -674,42 +842,20 @@ public final class EmojiPagerContentComponent: Component { self.scrollView.clipsToBounds = false self.addSubview(self.scrollView) - //self.clipsToBounds = true - self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) - /*self.useSublayerTransformForActivation = false - self.shouldBegin = { [weak self] point in - guard let strongSelf = self else { - return false - } - if let item = strongSelf.item(atPoint: point), let itemLayer = strongSelf.visibleItemLayers[item.1] { - strongSelf.currentContextGestureItemKey = item.1 - strongSelf.targetLayerForActivationProgress = itemLayer - return true - } else { - return false - } - } - self.contextGesture?.cancelGesturesOnActivation = { [weak self] in - guard let strongSelf = self else { - return - } - strongSelf.scrollView.panGestureRecognizer.state = .failed - }*/ - 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] else { + guard let item = strongSelf.item(atPoint: point), let itemLayer = strongSelf.visibleItemLayers[item.1], let file = item.0.file else { return nil } let context = component.context let accountPeerId = context.account.peerId return combineLatest( - context.engine.stickers.isStickerSaved(id: item.0.file.fileId), + 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 { @@ -734,9 +880,9 @@ public final class EmojiPagerContentComponent: Component { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - sendSticker(.standalone(media: item.0.file), true, false, nil, false, animationNode.view, animationNode.bounds, nil) + 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: item.0.file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) + sendSticker(.standalone(media: file), true, false, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -748,9 +894,9 @@ public final class EmojiPagerContentComponent: Component { }, action: { _, f in if let strongSelf = self, let peekController = strongSelf.peekController { if let animationNode = (peekController.contentNode as? StickerPreviewPeekContentNode)?.animationNode { - let _ = sendSticker(.standalone(media: item.0.file), false, true, nil, false, animationNode.view, animationNode.bounds, nil) + 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: item.0.file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) + let _ = sendSticker(.standalone(media: file), false, true, nil, false, imageNode.view, imageNode.bounds, nil) } } f(.default) @@ -762,11 +908,11 @@ public final class EmojiPagerContentComponent: Component { f(.default) let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let _ = (context.engine.stickers.toggleStickerSaved(file: item.0.file, saved: !isStarred) + let _ = (context.engine.stickers.toggleStickerSaved(file: file, saved: !isStarred) |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - component.inputInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: item.0.file, title: nil, text: !isStarred ? presentationData.strings.Conversation_StickerAddedToFavorites : presentationData.strings.Conversation_StickerRemovedFromFavorites, undoText: nil), elevatedLayout: false, action: { _ in return false })) + component.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 @@ -775,7 +921,7 @@ public final class EmojiPagerContentComponent: Component { } else { text = presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - component.inputInteraction.presentGlobalOverlayController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: item.0.file, title: presentationData.strings.Premium_MaxFavedStickersTitle("\(limit)").string, text: text, undoText: nil), elevatedLayout: false, action: { action in + component.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.inputInteraction.pushController(controller) @@ -793,9 +939,9 @@ public final class EmojiPagerContentComponent: Component { }, action: { _, f in f(.default) - loop: for attribute in item.0.file.attributes { + loop: for attribute in file.attributes { switch attribute { - case let .Sticker(_, packReference, _): + case let .CustomEmoji(_, _, packReference): if let packReference = packReference { let controller = StickerPackScreen(context: context, updatedPresentationData: nil, mainStickerPack: packReference, stickerPacks: [packReference], parentNavigationController: component.inputInteraction.navigationController(), sendSticker: { file, sourceView, sourceRect in //return component.inputInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil) @@ -813,7 +959,7 @@ public final class EmojiPagerContentComponent: Component { })) ) - return (strongSelf, strongSelf.scrollView.convert(itemLayer.frame, to: strongSelf), StickerPreviewPeekContent(account: context.account, theme: presentationData.theme, strings: presentationData.strings, item: .pack(item.0.file), isLocked: item.0.file.isPremiumSticker && !hasPremium, menu: menuItems, openPremiumIntro: { + 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.inputInteraction.pushController(controller) })) @@ -848,7 +994,9 @@ public final class EmojiPagerContentComponent: Component { } strongSelf.updatePreviewingItem(item: item, animated: true)*/ }) + self.peekRecognizer = peekRecognizer self.addGestureRecognizer(peekRecognizer) + self.peekRecognizer?.isEnabled = false } required init?(coder: NSCoder) { @@ -864,12 +1012,28 @@ public final class EmojiPagerContentComponent: Component { return false } - public func scrollToItemGroup(groupId: AnyHashable) { - guard let itemLayout = self.itemLayout else { + public func scrollToItemGroup(id supergroupId: AnyHashable, subgroupId: Int32?) { + guard let component = self.component, let itemLayout = self.itemLayout else { return } - for group in itemLayout.itemGroupLayouts { - if group.id == groupId { + 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) @@ -877,14 +1041,56 @@ public final class EmojiPagerContentComponent: Component { self.keepTopPanelVisibleUntilScrollingInput = true - self.scrollView.scrollRectToVisible(CGRect(origin: group.frame.origin.offsetBy(dx: 0.0, dy: floor(-itemLayout.verticalGroupSpacing / 2.0) - 41.0), size: CGSize(width: 1.0, height: self.scrollView.bounds.height)), animated: true) + let anchorFrame: CGRect + if let subgroupItemIndex = subgroupItemIndex { + anchorFrame = itemLayout.frame(groupIndex: groupIndex, itemIndex: subgroupItemIndex) + } else { + anchorFrame = group.frame + } + + self.scrollView.scrollRectToVisible(CGRect(origin: anchorFrame.origin.offsetBy(dx: 0.0, dy: floor(-itemLayout.verticalGroupSpacing / 2.0) - 41.0), size: CGSize(width: 1.0, height: self.scrollView.bounds.height)), animated: true) } } } @objc private func tapGesture(_ recognizer: UITapGestureRecognizer) { + guard let component = self.component else { + return + } if case .ended = recognizer.state { - if let component = self.component, let (item, itemKey) = self.item(atPoint: recognizer.location(in: self)), let itemLayer = self.visibleItemLayers[itemKey] { + 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) { + for group in component.itemGroups { + if group.groupId == id { + if group.isPremium && !self.expandedPremiumGroups.contains(id) { + if self.expandedPremiumGroups.contains(id) { + self.expandedPremiumGroups.remove(id) + } else { + self.expandedPremiumGroups.insert(id) + } + + let previousItemLayout = self.itemLayout + + let transition = Transition(animation: .curve(duration: 0.25, curve: .easeInOut)) + self.state?.updated(transition: transition) + + if let previousItemLayout = previousItemLayout, let itemLayout = self.itemLayout { + let boundsOffset = itemLayout.contentSize.height - previousItemLayout.contentSize.height + self.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.scrollView.contentOffset.y + boundsOffset), animated: false) + transition.animateBoundsOrigin(view: self.scrollView, from: CGPoint(x: 0.0, y: -boundsOffset), to: CGPoint(), additive: true) + } + + return + } else { + break outer + } + } + } + } + } + + if let (item, itemKey) = self.item(atPoint: recognizer.location(in: self)), let itemLayer = self.visibleItemLayers[itemKey] { component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) } } @@ -926,7 +1132,7 @@ public final class EmojiPagerContentComponent: Component { return } - self.updateVisibleItems(attemptSynchronousLoads: false) + self.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false) self.updateScrollingOffset(isReset: false, transition: .immediate) } @@ -1000,7 +1206,7 @@ public final class EmojiPagerContentComponent: Component { self.updateScrollingOffset(isReset: false, transition: transition) } - private func updateVisibleItems(attemptSynchronousLoads: Bool) { + private func updateVisibleItems(transition: Transition, attemptSynchronousLoads: Bool) { guard let component = self.component, let theme = self.theme, let itemLayout = self.itemLayout else { return } @@ -1009,6 +1215,8 @@ public final class EmojiPagerContentComponent: Component { var validIds = Set() var validGroupHeaderIds = Set() + var validGroupBorderIds = Set() + var validGroupPremiumButtonIds = Set() let effectiveVisibleBounds = CGRect(origin: self.scrollView.bounds.origin, size: self.effectiveVisibleSize) let topVisibleDetectionBounds = effectiveVisibleBounds.offsetBy(dx: 0.0, dy: 41.0) @@ -1018,49 +1226,180 @@ public final class EmojiPagerContentComponent: Component { let itemGroupLayout = itemLayout.itemGroupLayouts[groupItems.groupIndex] if topVisibleGroupId == nil && itemGroupLayout.frame.intersects(topVisibleDetectionBounds) { - topVisibleGroupId = groupItems.id + topVisibleGroupId = groupItems.supergroupId } + var headerSize: CGSize? + var headerSizeUpdated = false if let title = itemGroup.title { - validGroupHeaderIds.insert(itemGroup.id) - let groupHeaderView: ComponentView - if let current = self.visibleGroupHeaders[itemGroup.id] { - groupHeaderView = current + validGroupHeaderIds.insert(itemGroup.groupId) + let groupHeaderLayer: GroupHeaderLayer + var groupHeaderTransition = transition + if let current = self.visibleGroupHeaders[itemGroup.groupId] { + groupHeaderLayer = current } else { - groupHeaderView = ComponentView() - self.visibleGroupHeaders[itemGroup.id] = groupHeaderView + groupHeaderTransition = .immediate + groupHeaderLayer = GroupHeaderLayer() + self.visibleGroupHeaders[itemGroup.groupId] = groupHeaderLayer + self.scrollView.layer.addSublayer(groupHeaderLayer) } - let groupHeaderSize = groupHeaderView.update( - transition: .immediate, - component: AnyComponent(Text( - text: title.uppercased(), font: Font.medium(12.0), color: theme.chat.inputMediaPanel.stickersSectionTextColor - )), - environment: {}, - containerSize: CGSize(width: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right, height: 100.0) - ) - if let view = groupHeaderView.view { - if view.superview == nil { - self.scrollView.addSubview(view) + let (groupHeaderSize, groupHeaderHorizontalOffset) = groupHeaderLayer.update(theme: theme, title: title, isPremium: itemGroup.isPremium, constrainedWidth: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right - 32.0) + + if groupHeaderLayer.bounds.size != groupHeaderSize { + headerSizeUpdated = true + } + + let groupHeaderFrame = CGRect(origin: CGPoint(x: groupHeaderHorizontalOffset + floor((itemLayout.contentSize.width - groupHeaderSize.width - groupHeaderHorizontalOffset) / 2.0), y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) + groupHeaderLayer.bounds = CGRect(origin: CGPoint(), size: groupHeaderFrame.size) + groupHeaderTransition.setPosition(layer: groupHeaderLayer, position: CGPoint(x: groupHeaderFrame.midX, y: groupHeaderFrame.midY)) + headerSize = CGSize(width: groupHeaderSize.width + groupHeaderHorizontalOffset, height: groupHeaderSize.height) + } + + if itemGroup.isPremium { + 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) + + groupBorderLayer.strokeColor = theme.chat.inputMediaPanel.stickersSectionTextColor.cgColor + groupBorderLayer.lineWidth = 1.6 + groupBorderLayer.lineCap = .round + groupBorderLayer.fillColor = nil + } + + let groupBorderHorizontalInset: CGFloat = itemLayout.containerInsets.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)) + + let radius: CGFloat = 16.0 + + if groupBorderLayer.bounds.size != groupBorderFrame.size || headerSizeUpdated { + let headerWidth: CGFloat + if let headerSize = headerSize { + headerWidth = headerSize.width + 14.0 + } else { + headerWidth = 0.0 + } + let path = CGMutablePath() + 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 self.expandedPremiumGroups.contains(itemGroup.groupId) { + 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 + } + + //TODO:localize + let groupPremiumButtonSize = groupPremiumButton.update( + transition: groupPremiumButtonTransition, + component: AnyComponent(SolidRoundedButtonComponent( + title: "Unlock \(itemGroup.title ?? "Emoji")", + theme: SolidRoundedButtonComponent.Theme( + backgroundColor: .black, + backgroundColors: [ + UIColor(rgb: 0x0077ff), + UIColor(rgb: 0x6b93ff), + UIColor(rgb: 0x8878ff), + UIColor(rgb: 0xe46ace) + ], + foregroundColor: .white + ), + font: .bold, + fontSize: 17.0, + height: 50.0, + cornerRadius: radius, + gloss: true, + animationName: "premium_unlock", + iconPosition: .right, + iconSpacing: 4.0, + action: { [weak self] in + guard let strongSelf = self, let component = strongSelf.component else { + return + } + component.inputInteraction.openPremiumSection() + } + )), + environment: {}, + containerSize: CGSize(width: itemLayout.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right, height: itemLayout.premiumButtonHeight) + ) + let groupPremiumButtonFrame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.maxY - groupPremiumButtonSize.height + 1.0), size: groupPremiumButtonSize) + if let view = groupPremiumButton.view { + var animateIn = false + if view.superview == nil { + view.layer.anchorPoint = CGPoint(x: 0.5, y: 0.0) + 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) + } } - view.frame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) } } for index in groupItems.groupItems.lowerBound ..< groupItems.groupItems.upperBound { let item = itemGroup.items[index] - let itemId = ItemLayer.Key(groupId: itemGroup.id, fileId: item.file.fileId) + let itemId = ItemLayer.Key(groupId: itemGroup.groupId, fileId: item.file?.fileId, staticEmoji: item.staticEmoji) validIds.insert(itemId) - let itemDimensions = item.file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0) + 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.fitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) var updateItemLayerPlaceholder = false + var itemTransition = transition let itemLayer: ItemLayer if let current = self.visibleItemLayers[itemId] { itemLayer = current } else { updateItemLayerPlaceholder = true + itemTransition = .immediate itemLayer = ItemLayer( item: item, @@ -1068,17 +1407,18 @@ public final class EmojiPagerContentComponent: Component { groupId: "keyboard-\(Int(itemLayout.nativeItemSize))", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, + staticEmoji: item.staticEmoji, cache: component.animationCache, renderer: component.animationRenderer, placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), - displayPremiumBadgeIfAvailable: true, + displayPremiumBadgeIfAvailable: itemGroup.displayPremiumBadges, pointSize: itemNativeFitSize, onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder in guard let strongSelf = self else { return } - if displayPlaceholder { + if displayPlaceholder, let file = item.file { if let itemLayer = strongSelf.visibleItemLayers[itemId] { let placeholderView: ItemPlaceholderView if let current = strongSelf.visibleItemPlaceholderViews[itemId] { @@ -1086,7 +1426,7 @@ public final class EmojiPagerContentComponent: Component { } else { placeholderView = ItemPlaceholderView( context: component.context, - file: item.file, + file: file, shimmerView: strongSelf.shimmerHostView, color: nil, size: itemNativeFitSize @@ -1121,16 +1461,12 @@ public final class EmojiPagerContentComponent: Component { let itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY) let itemBounds = CGRect(origin: CGPoint(), size: itemFrame.size) - if itemLayer.position != itemPosition { - itemLayer.position = itemPosition - } - if itemLayer.bounds != itemBounds { - itemLayer.bounds = CGRect(origin: CGPoint(), size: itemFrame.size) - } + itemTransition.setPosition(layer: itemLayer, position: itemPosition) + itemTransition.setBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) if let placeholderView = self.visibleItemPlaceholderViews[itemId] { if placeholderView.layer.position != itemPosition || placeholderView.layer.bounds != itemBounds { - placeholderView.frame = itemFrame + itemTransition.setFrame(view: placeholderView, frame: itemFrame) placeholderView.update(size: itemFrame.size) } } else if updateItemLayerPlaceholder { @@ -1159,16 +1495,38 @@ public final class EmojiPagerContentComponent: Component { } var removedGroupHeaderIds: [AnyHashable] = [] - for (id, groupHeaderView) in self.visibleGroupHeaders { + for (id, groupHeaderLayer) in self.visibleGroupHeaders { if !validGroupHeaderIds.contains(id) { removedGroupHeaderIds.append(id) - groupHeaderView.view?.removeFromSuperview() + groupHeaderLayer.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() + } + } + 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) + } + if let topVisibleGroupId = topVisibleGroupId { self.activeItemUpdated?.invoke((topVisibleGroupId, .immediate)) } @@ -1184,6 +1542,9 @@ public final class EmojiPagerContentComponent: Component { func update(component: EmojiPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { self.component = component + self.state = state + + self.peekRecognizer?.isEnabled = component.itemLayoutType == .detailed let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value @@ -1202,13 +1563,24 @@ public final class EmojiPagerContentComponent: Component { var itemGroups: [ItemGroupDescription] = [] for itemGroup in component.itemGroups { itemGroups.append(ItemGroupDescription( - id: itemGroup.id, + supergroupId: itemGroup.supergroupId, + groupId: itemGroup.groupId, hasTitle: itemGroup.title != nil, + isPremium: itemGroup.isPremium, itemCount: itemGroup.items.count )) } - let itemLayout = ItemLayout(width: availableSize.width, containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top + 9.0, left: pagerEnvironment.containerInsets.left + 12.0, bottom: 9.0 + pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right + 12.0), itemGroups: itemGroups, itemLayoutType: component.itemLayoutType) + var itemTransition = transition + + let itemLayout = ItemLayout(width: availableSize.width, containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top + 9.0, left: pagerEnvironment.containerInsets.left + 12.0, bottom: 9.0 + pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right + 12.0), itemGroups: itemGroups, itemLayoutType: component.itemLayoutType, expandedPremiumGroups: expandedPremiumGroups) + if let previousItemLayout = self.itemLayout { + if previousItemLayout.width != itemLayout.width { + itemTransition = .immediate + } + } else { + itemTransition = .immediate + } self.itemLayout = itemLayout self.ignoreScrolling = true @@ -1229,7 +1601,7 @@ public final class EmojiPagerContentComponent: Component { let effectiveVisibleSize = strongSelf.scrollView.bounds.size if strongSelf.effectiveVisibleSize != effectiveVisibleSize { strongSelf.effectiveVisibleSize = effectiveVisibleSize - strongSelf.updateVisibleItems(attemptSynchronousLoads: false) + strongSelf.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false) } }) } @@ -1243,7 +1615,7 @@ public final class EmojiPagerContentComponent: Component { self.previousScrollingOffset = ScrollingOffsetState(value: scrollView.contentOffset.y, isDraggingOrDecelerating: scrollView.isDragging || scrollView.isDecelerating) self.ignoreScrolling = false - self.updateVisibleItems(attemptSynchronousLoads: !(scrollView.isDragging || scrollView.isDecelerating)) + self.updateVisibleItems(transition: itemTransition, attemptSynchronousLoads: !(scrollView.isDragging || scrollView.isDecelerating)) return availableSize } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 27c9e26502..33c1f5cbfc 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -8,6 +8,8 @@ import TelegramCore import Postbox import BlurredBackgroundComponent import BundleIconComponent +import AudioToolbox +import SwiftSignalKit public final class EntityKeyboardChildEnvironment: Equatable { public let theme: PresentationTheme @@ -41,6 +43,11 @@ public final class EntityKeyboardComponent: Component { } } + private enum ReorderCategory { + case stickers + case emoji + } + public struct GifSearchEmoji: Equatable { public var emoji: String public var file: TelegramMediaFile @@ -199,6 +206,7 @@ public final class EntityKeyboardComponent: Component { //TODO:localize topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: "recent", + isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( imageName: "Chat/Input/Media/RecentTabIcon", theme: component.theme, @@ -210,6 +218,7 @@ public final class EntityKeyboardComponent: Component { )) topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: "trending", + isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( imageName: "Chat/Input/Media/TrendingGifs", theme: component.theme, @@ -222,6 +231,7 @@ public final class EntityKeyboardComponent: Component { for emoji in component.availableGifSearchEmojies { topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: emoji.emoji, + isReorderable: false, content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( context: component.stickerContent.context, file: emoji.file, @@ -248,7 +258,9 @@ public final class EntityKeyboardComponent: Component { theme: component.theme, items: topGifItems, defaultActiveItemId: defaultActiveGifItemId, - activeContentItemIdUpdated: gifsContentItemIdUpdated + activeContentItemIdUpdated: gifsContentItemIdUpdated, + reorderItems: { _ in + } )))) contentIcons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputGifsIcon", @@ -265,56 +277,53 @@ public final class EntityKeyboardComponent: Component { self?.openSearch() } ).minSize(CGSize(width: 38.0, height: 38.0))))) - /*contentAccessoryRightButtons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(Button( - content: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/EntityInputSettingsIcon", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: nil - )), - action: { - } - ).minSize(CGSize(width: 38.0, height: 38.0)))))*/ var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] for itemGroup in component.stickerContent.itemGroups { - if let id = itemGroup.id.base as? String { + if let id = itemGroup.supergroupId.base as? String { let iconMapping: [String: String] = [ + "saved": "Chat/Input/Media/SavedStickersTabIcon", "recent": "Chat/Input/Media/RecentTabIcon", "premium": "Chat/Input/Media/PremiumIcon" ] let titleMapping: [String: String] = [ + "saved": "Saved", "recent": "Recent", "premium": "Premium" ] if let iconName = iconMapping[id], let title = titleMapping[id] { topStickerItems.append(EntityKeyboardTopPanelComponent.Item( - id: itemGroup.id, + id: itemGroup.supergroupId, + isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( imageName: iconName, theme: component.theme, title: title, pressed: { [weak self] in - self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.id) + self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.supergroupId, subgroupId: nil) } )) )) } } else { if !itemGroup.items.isEmpty { - topStickerItems.append(EntityKeyboardTopPanelComponent.Item( - id: itemGroup.id, - content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( - context: component.stickerContent.context, - file: itemGroup.items[0].file, - animationCache: component.stickerContent.animationCache, - animationRenderer: component.stickerContent.animationRenderer, - theme: component.theme, - title: itemGroup.title ?? "", - pressed: { [weak self] in - self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.id) - } + if let file = itemGroup.items[0].file { + topStickerItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: true, + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.stickerContent.context, + file: file, + animationCache: component.stickerContent.animationCache, + animationRenderer: component.stickerContent.animationRenderer, + theme: component.theme, + title: itemGroup.title ?? "", + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.supergroupId, subgroupId: nil) + } + )) )) - )) + } } } } @@ -323,7 +332,13 @@ public final class EntityKeyboardComponent: Component { contentTopPanels.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, items: topStickerItems, - activeContentItemIdUpdated: stickersContentItemIdUpdated + activeContentItemIdUpdated: stickersContentItemIdUpdated, + reorderItems: { [weak self] items in + guard let strongSelf = self else { + return + } + strongSelf.reorderPacks(category: .stickers, items: items) + } )))) contentIcons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputStickersIcon", @@ -356,26 +371,53 @@ public final class EntityKeyboardComponent: Component { var topEmojiItems: [EntityKeyboardTopPanelComponent.Item] = [] for itemGroup in component.emojiContent.itemGroups { if !itemGroup.items.isEmpty { - topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( - id: itemGroup.id, - content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( - context: component.emojiContent.context, - file: itemGroup.items[0].file, - animationCache: component.emojiContent.animationCache, - animationRenderer: component.emojiContent.animationRenderer, - theme: component.theme, - title: itemGroup.title ?? "", - pressed: { [weak self] in - self?.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.id) - } - )) - )) + if let id = itemGroup.groupId.base as? String { + if id == "static" { + topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: false, + content: AnyComponent(EntityKeyboardStaticStickersPanelComponent( + theme: component.theme, + 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: true, + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: component.emojiContent.context, + file: file, + 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, - activeContentItemIdUpdated: emojiContentItemIdUpdated + activeContentItemIdUpdated: emojiContentItemIdUpdated, + reorderItems: { [weak self] items in + guard let strongSelf = self else { + return + } + strongSelf.reorderPacks(category: .emoji, items: items) + } )))) contentIcons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputEmojiIcon", @@ -404,9 +446,11 @@ public final class EntityKeyboardComponent: Component { )), action: { deleteBackwards() + AudioServicesPlaySystemSound(1155) } ).withHoldAction({ deleteBackwards() + AudioServicesPlaySystemSound(1155) }).minSize(CGSize(width: 38.0, height: 38.0))))) let panelHideBehavior: PagerComponentPanelHideBehavior @@ -441,6 +485,7 @@ public final class EntityKeyboardComponent: Component { bottomInset: component.bottomInset, deleteBackwards: { [weak self] in self?.component?.emojiContent.inputInteraction.deleteBackwards() + AudioServicesPlaySystemSound(0x451) } )), panelStateUpdated: { [weak self] panelState, transition in @@ -599,11 +644,39 @@ public final class EntityKeyboardComponent: Component { component.hideInputUpdated(false, false, Transition(animation: .curve(duration: 0.4, curve: .spring))) } - private func scrollToItemGroup(contentId: String, groupId: AnyHashable) { + private func scrollToItemGroup(contentId: String, groupId: AnyHashable, subgroupId: Int32?) { if let pagerView = self.pagerView.findTaggedView(tag: EmojiPagerContentComponent.Tag(id: contentId)) as? EmojiPagerContentComponent.View { - pagerView.scrollToItemGroup(groupId: groupId) + pagerView.scrollToItemGroup(id: groupId, subgroupId: subgroupId) } } + + 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.stickerContent.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 { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift index 60d71d5d6d..ba093de32b 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -67,8 +67,6 @@ final class EntityKeyboardTopContainerPanelComponent: Component { private var visibilityFraction: CGFloat = 1.0 - private var hasExpandedPanels: Bool = false - override init(frame: CGRect) { super.init(frame: frame) @@ -84,6 +82,8 @@ final class EntityKeyboardTopContainerPanelComponent: Component { let intrinsicHeight: CGFloat = 41.0 let height = intrinsicHeight + let isExpanded = availableSize.height > 41.0 + let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value var transitionOffsetFraction: CGFloat = 0.0 @@ -133,6 +133,10 @@ final class EntityKeyboardTopContainerPanelComponent: Component { self.addSubview(panelView.view) } + if !isExpanded { + panelView.isExpanded = false + } + let panelId = panel.id let _ = panelView.view.update( transition: panelTransition, @@ -198,6 +202,9 @@ final class EntityKeyboardTopContainerPanelComponent: Component { guard let panelView = self.panelViews[id] else { return } + if panelView.isExpanded == isExpanded { + return + } panelView.isExpanded = isExpanded var hasExpanded = false @@ -207,12 +214,8 @@ final class EntityKeyboardTopContainerPanelComponent: Component { break } } - - if self.hasExpandedPanels != hasExpanded { - self.hasExpandedPanels = hasExpanded - - self.panelEnvironment?.isExpandedUpdated(self.hasExpandedPanels, transition) - } + + self.panelEnvironment?.isExpandedUpdated(hasExpanded, transition) } override public func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 6a685fcf26..c8ac47cfe5 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -11,6 +11,7 @@ import AnimationCache import MultiAnimationRenderer import AccountContext import MultilineTextComponent +import LottieAnimationComponent final class EntityKeyboardAnimationTopPanelComponent: Component { typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment @@ -94,14 +95,15 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { if self.itemLayer == nil { let itemLayer = EmojiPagerContentComponent.View.ItemLayer( item: EmojiPagerContentComponent.Item( - emoji: "", file: component.file, - stickerPackItem: nil + staticEmoji: nil, + subgroupId: nil ), context: component.context, groupId: "topPanel", attemptSynchronousLoad: false, file: component.file, + staticEmoji: nil, cache: component.animationCache, renderer: component.animationRenderer, placeholderColor: .lightGray, @@ -323,30 +325,429 @@ final class EntityKeyboardIconTopPanelComponent: Component { } } +final class EntityKeyboardStaticStickersPanelComponent: Component { + typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment + + let theme: PresentationTheme + let pressed: (EmojiPagerContentComponent.StaticEmojiSegment) -> Void + + init( + theme: PresentationTheme, + pressed: @escaping (EmojiPagerContentComponent.StaticEmojiSegment) -> Void + ) { + self.theme = theme + self.pressed = pressed + } + + static func ==(lhs: EntityKeyboardStaticStickersPanelComponent, rhs: EntityKeyboardStaticStickersPanelComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + + return true + } + + final class View: UIView, UIScrollViewDelegate { + private let scrollView: UIScrollView + private var visibleItemViews: [EmojiPagerContentComponent.StaticEmojiSegment: ComponentView] = [:] + + private var component: EntityKeyboardStaticStickersPanelComponent? + + private var ignoreScrolling: Bool = false + + override init(frame: CGRect) { + 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.delegate = self + self.addSubview(self.scrollView) + + self.clipsToBounds = true + + 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 { + let scrollViewLocation = recognizer.location(in: self.scrollView) + for (id, itemView) in self.visibleItemViews { + if let view = itemView.view, view.frame.insetBy(dx: -4.0, dy: -4.0).contains(scrollViewLocation) { + self.component?.pressed(id) + break + } + } + } + } + + 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 else { + return + } + + let _ = component + + var validItemIds = Set() + let visibleBounds = self.scrollView.bounds + + let componentHeight: CGFloat = 32.0 + + let items = EmojiPagerContentComponent.StaticEmojiSegment.allCases + let itemSize: CGFloat = 28.0 + let itemSpacing: CGFloat = 4.0 + let sideInset: CGFloat = 2.0 + for i in 0 ..< items.count { + let itemFrame = CGRect(origin: CGPoint(x: sideInset + CGFloat(i) * (itemSize + itemSpacing), y: floor(componentHeight - itemSize) / 2.0), size: CGSize(width: itemSize, height: itemSize)) + if visibleBounds.intersects(itemFrame) { + let item = items[i] + validItemIds.insert(item) + + let itemView: ComponentView + if let current = self.visibleItemViews[item] { + itemView = current + } else { + itemView = ComponentView() + self.visibleItemViews[item] = itemView + } + + 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 _ = itemView.update( + transition: .immediate, + component: AnyComponent(LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: animationName, + colors: ["__allcolors__": component.theme.chat.inputMediaPanel.panelIconColor], + mode: animateAppearingItems ? .animating(loop: false) : .still(position: .end) + ), + size: CGSize(width: itemSize, height: itemSize) + )), + environment: {}, + containerSize: CGSize(width: itemSize, height: itemSize) + ) + if let view = itemView.view { + if view.superview == nil { + self.scrollView.addSubview(view) + } + view.frame = itemFrame + } + } + } + + 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 { + self.layer.cornerRadius = availableSize.height / 2.0 + + let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value + + self.component = component + + let itemSize: CGFloat = 28.0 + let itemSpacing: CGFloat = 4.0 + let sideInset: CGFloat = 2.0 + let itemCount = EmojiPagerContentComponent.StaticEmojiSegment.allCases.count + + self.ignoreScrolling = true + self.scrollView.frame = CGRect(origin: CGPoint(), size: CGSize(width: max(availableSize.width, 150.0), height: availableSize.height)) + self.scrollView.contentSize = CGSize(width: sideInset * 2.0 + itemSize * CGFloat(itemCount) + itemSpacing * CGFloat(itemCount - 1), height: availableSize.height) + self.ignoreScrolling = false + + self.updateVisibleItems(transition: .immediate, animateAppearingItems: false) + + if !itemEnvironment.isHighlighted && self.scrollView.contentOffset.x != 0.0 { + self.scrollView.setContentOffset(CGPoint(), animated: true) + } + + 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 - init(isExpanded: Bool) { + init(isExpanded: Bool, isHighlighted: Bool) { self.isExpanded = isExpanded + self.isHighlighted = isHighlighted } static func ==(lhs: EntityKeyboardTopPanelItemEnvironment, rhs: EntityKeyboardTopPanelItemEnvironment) -> Bool { if lhs.isExpanded != rhs.isExpanded { return false } + if lhs.isHighlighted != rhs.isHighlighted { + 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 + } + + 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, content: AnyComponent) { + init(id: AnyHashable, isReorderable: Bool, content: AnyComponent) { self.id = id + self.isReorderable = isReorderable self.content = content } @@ -354,6 +755,9 @@ final class EntityKeyboardTopPanelComponent: Component { if lhs.id != rhs.id { return false } + if lhs.isReorderable != rhs.isReorderable { + return false + } if lhs.content != rhs.content { return false } @@ -366,17 +770,20 @@ final class EntityKeyboardTopPanelComponent: Component { let items: [Item] let defaultActiveItemId: AnyHashable? let activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)> + let reorderItems: ([Item]) -> Void init( theme: PresentationTheme, items: [Item], defaultActiveItemId: AnyHashable? = nil, - activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)> + activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)>, + reorderItems: @escaping ([Item]) -> Void ) { self.theme = theme self.items = items self.defaultActiveItemId = defaultActiveItemId self.activeContentItemIdUpdated = activeContentItemIdUpdated + self.reorderItems = reorderItems } static func ==(lhs: EntityKeyboardTopPanelComponent, rhs: EntityKeyboardTopPanelComponent) -> Bool { @@ -398,24 +805,79 @@ final class EntityKeyboardTopPanelComponent: Component { 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 sideInset: CGFloat = 7.0 let itemSize: CGSize + let staticItemSize: CGSize + let staticExpandedItemSize: CGSize let innerItemSize: CGSize let itemSpacing: CGFloat = 15.0 - let itemCount: Int let contentSize: CGSize let isExpanded: Bool + let items: [Item] - init(itemCount: Int, isExpanded: Bool, height: CGFloat) { + init(isExpanded: Bool, height: CGFloat, items: [ItemDescription]) { self.isExpanded = isExpanded self.itemSize = self.isExpanded ? CGSize(width: 54.0, height: 68.0) : CGSize(width: 32.0, height: 32.0) + self.staticItemSize = self.itemSize + self.staticExpandedItemSize = self.isExpanded ? CGSize(width: 150.0, height: 68.0) : CGSize(width: 150.0, height: 32.0) self.innerItemSize = self.isExpanded ? CGSize(width: 50.0, height: 62.0) : CGSize(width: 28.0, height: 28.0) - self.itemCount = itemCount - self.contentSize = CGSize(width: sideInset * 2.0 + CGFloat(itemCount) * self.itemSize.width + CGFloat(max(0, itemCount - 1)) * itemSpacing, height: height) + + var contentSize = CGSize(width: sideInset, height: height) + var resultItems: [Item] = [] + + var isFirst = true + let itemY = 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 CGRect(origin: CGPoint(x: sideInset + CGFloat(index) * (self.itemSize.width + self.itemSpacing), y: floor((self.contentSize.height - self.itemSize.height) / 2.0)), size: self.itemSize) + return self.items[index].frame } func contentFrame(containerFrame: CGRect) -> CGRect { @@ -427,19 +889,21 @@ final class EntityKeyboardTopPanelComponent: Component { } func contentFrame(at index: Int) -> CGRect { - return self.contentFrame(containerFrame: self.containerFrame(at: index)) + return self.items[index].innerFrame } func visibleItemRange(for rect: CGRect) -> (minIndex: Int, maxIndex: Int) { - let offsetRect = rect.offsetBy(dx: -self.sideInset, dy: 0.0) - var minVisibleColumn = Int(floor((offsetRect.minX - self.itemSpacing) / (self.itemSize.width + self.itemSpacing))) - minVisibleColumn = max(0, minVisibleColumn) - let maxVisibleColumn = Int(ceil((offsetRect.maxX - self.itemSpacing) / (self.itemSize.width + self.itemSpacing))) - - let minVisibleIndex = minVisibleColumn - let maxVisibleIndex = min(maxVisibleColumn, self.itemCount - 1) - - return (minVisibleIndex, maxVisibleIndex) + 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) } } @@ -447,10 +911,20 @@ final class EntityKeyboardTopPanelComponent: Component { 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 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 isExpanded: Bool = false @@ -460,6 +934,7 @@ final class EntityKeyboardTopPanelComponent: Component { private var activeContentItemId: AnyHashable? private var component: EntityKeyboardTopPanelComponent? + weak var state: EmptyComponentState? private var environment: EntityKeyboardTopContainerPanelEnvironment? override init(frame: CGRect) { @@ -467,8 +942,8 @@ final class EntityKeyboardTopPanelComponent: Component { self.highlightedIconBackgroundView = UIView() self.highlightedIconBackgroundView.isUserInteractionEnabled = false - self.highlightedIconBackgroundView.layer.cornerRadius = 10.0 self.highlightedIconBackgroundView.clipsToBounds = true + self.highlightedIconBackgroundView.isHidden = true super.init(frame: frame) @@ -483,6 +958,7 @@ final class EntityKeyboardTopPanelComponent: Component { } self.scrollView.showsVerticalScrollIndicator = false self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.alwaysBounceHorizontal = true self.scrollView.delegate = self self.addSubview(self.scrollView) @@ -496,6 +972,50 @@ final class EntityKeyboardTopPanelComponent: Component { } return strongSelf.scrollView.contentOffset.x > 0.0 } + + self.addGestureRecognizer(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 + } + strongSelf.updateIsReordering(isActive) + } + )) } required init?(coder: NSCoder) { @@ -525,8 +1045,20 @@ final class EntityKeyboardTopPanelComponent: Component { } private func updateIsDragging(_ isDragging: Bool) { - if !isDragging { - if !self.isDragging { + 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 } @@ -536,7 +1068,7 @@ final class EntityKeyboardTopPanelComponent: Component { return } strongSelf.draggingStoppedTimer = nil - strongSelf.isDragging = false + strongSelf.isDraggingOrReordering = false guard let environment = strongSelf.environment else { return } @@ -548,8 +1080,8 @@ final class EntityKeyboardTopPanelComponent: Component { self.draggingStoppedTimer?.invalidate() self.draggingStoppedTimer = nil - if !self.isDragging { - self.isDragging = true + if !self.isDraggingOrReordering { + self.isDraggingOrReordering = true guard let environment = self.environment else { return @@ -559,8 +1091,91 @@ final class EntityKeyboardTopPanelComponent: Component { } } + 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) + } + } + + 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() + } + + 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) + + for i in 0 ..< self.items.count { + if !self.items[i].isReorderable { + continue + } + let containerFrame = itemLayout.containerFrame(at: i) + if containerFrame.intersects(reorderingItemContainerView.frame) { + let temporaryReorderingOrderIndex: (id: AnyHashable, index: Int) = (currentReorderingItemId, i) + if self.temporaryReorderingOrderIndex?.id != temporaryReorderingOrderIndex.id || self.temporaryReorderingOrderIndex?.index != temporaryReorderingOrderIndex.index { + self.temporaryReorderingOrderIndex = temporaryReorderingOrderIndex + self.state?.updated(transition: Transition(animation: .curve(duration: 0.3, curve: .spring))) + } + break + } + } + } + private func updateVisibleItems(attemptSynchronousLoads: Bool, transition: Transition) { - guard let component = self.component, let itemLayout = self.itemLayout else { + guard let itemLayout = self.itemLayout else { return } @@ -569,9 +1184,9 @@ final class EntityKeyboardTopPanelComponent: Component { var validIds = Set() let visibleItemRange = itemLayout.visibleItemRange(for: visibleBounds) - if !component.items.isEmpty && visibleItemRange.maxIndex >= visibleItemRange.minIndex { + if !self.items.isEmpty && visibleItemRange.maxIndex >= visibleItemRange.minIndex { for index in visibleItemRange.minIndex ... visibleItemRange.maxIndex { - let item = component.items[index] + let item = self.items[index] validIds.insert(item.id) var itemTransition = transition @@ -590,7 +1205,7 @@ final class EntityKeyboardTopPanelComponent: Component { transition: itemTransition, component: item.content, environment: { - EntityKeyboardTopPanelItemEnvironment(isExpanded: itemLayout.isExpanded) + EntityKeyboardTopPanelItemEnvironment(isExpanded: itemLayout.isExpanded, isHighlighted: self.activeContentItemId == item.id) }, containerSize: itemOuterFrame.size ) @@ -618,6 +1233,7 @@ final class EntityKeyboardTopPanelComponent: Component { self.highlightedIconBackgroundView.backgroundColor = component.theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor } self.component = component + self.state = state if let defaultActiveItemId = component.defaultActiveItemId { self.activeContentItemId = defaultActiveItemId @@ -630,11 +1246,49 @@ final class EntityKeyboardTopPanelComponent: Component { let wasExpanded = self.isExpanded self.isExpanded = isExpanded + if !isExpanded { + if self.isDragging { + self.isDragging = false + } + if self.isReordering { + self.isReordering = false + } + 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(itemCount: component.items.count, isExpanded: isExpanded, height: availableSize.height) + let itemLayout = ItemLayout(isExpanded: isExpanded, 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 @@ -660,7 +1314,7 @@ final class EntityKeyboardTopPanelComponent: Component { let baseFrame = CGRect(origin: CGPoint(x: updatedItemFrame.minX, y: previousItemFrame.minY), size: previousItemFrame.size) for index in updatedVisibleRange.minIndex ..< updatedVisibleRange.maxIndex { let indexDifference = index - previousVisibleRange.minIndex - if let itemView = self.itemViews[component.items[index].id] { + if let itemView = self.itemViews[self.items[index].id] { let itemContainerOriginX = baseFrame.minX + CGFloat(indexDifference) * (previousItemLayout.itemSize.width + previousItemLayout.itemSpacing) let itemContainerFrame = CGRect(origin: CGPoint(x: itemContainerOriginX, y: baseFrame.minY), size: baseFrame.size) let itemOuterFrame = previousItemLayout.contentFrame(containerFrame: itemContainerFrame) @@ -685,11 +1339,23 @@ final class EntityKeyboardTopPanelComponent: Component { self.updateVisibleItems(attemptSynchronousLoads: !(self.scrollView.isDragging || self.scrollView.isDecelerating), transition: transition) if let activeContentItemId = self.activeContentItemId { - if let index = component.items.firstIndex(where: { $0.id == activeContentItemId }) { + if let index = self.items.firstIndex(where: { $0.id == activeContentItemId }) { let itemFrame = itemLayout.containerFrame(at: index) - transition.setPosition(view: self.highlightedIconBackgroundView, position: CGPoint(x: itemFrame.midX, y: itemFrame.midY)) - transition.setBounds(view: self.highlightedIconBackgroundView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + + var highlightTransition = transition + if self.highlightedIconBackgroundView.isHidden { + self.highlightedIconBackgroundView.isHidden = false + highlightTransition = .immediate + } + + highlightTransition.setCornerRadius(layer: self.highlightedIconBackgroundView.layer, cornerRadius: activeContentItemId.base is String ? 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) @@ -732,17 +1398,28 @@ final class EntityKeyboardTopPanelComponent: Component { guard let component = self.component, let itemLayout = self.itemLayout else { return } - + if self.activeContentItemId == itemId { + return + } self.activeContentItemId = itemId + + let _ = component + let _ = itemLayout + self.state?.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .spring))) - var found = false - for i in 0 ..< component.items.count { - if component.items[i].id == itemId { + /*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) - transition.setPosition(view: self.highlightedIconBackgroundView, position: CGPoint(x: itemFrame.midX, y: itemFrame.midY)) - transition.setBounds(view: self.highlightedIconBackgroundView, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + + 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) @@ -751,7 +1428,7 @@ final class EntityKeyboardTopPanelComponent: Component { } if !found { self.highlightedIconBackgroundView.isHidden = true - } + }*/ } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index c57bb93a13..b18ac64c11 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -18,6 +18,7 @@ import PagerComponent import SoftwareVideo import AVFoundation import PhotoResources +import ContextUI private class GifVideoLayer: AVSampleBufferDisplayLayer { private let context: AccountContext @@ -125,11 +126,14 @@ public final class GifPagerContentComponent: Component { public final class InputInteraction { public let performItemAction: (Item, UIView, CGRect) -> Void + public let openGifContextMenu: (TelegramMediaFile, UIView, CGRect, ContextGesture, Bool) -> Void public init( - performItemAction: @escaping (Item, UIView, CGRect) -> Void + performItemAction: @escaping (Item, UIView, CGRect) -> Void, + openGifContextMenu: @escaping (TelegramMediaFile, UIView, CGRect, ContextGesture, Bool) -> Void ) { self.performItemAction = performItemAction + self.openGifContextMenu = openGifContextMenu } } @@ -186,7 +190,7 @@ public final class GifPagerContentComponent: Component { return true } - public final class View: UIView, UIScrollViewDelegate { + public final class View: ContextControllerSourceView, UIScrollViewDelegate { private struct ItemGroupDescription: Equatable { let hasTitle: Bool let itemCount: Int @@ -406,12 +410,44 @@ public final class GifPagerContentComponent: Component { self.addSubview(self.scrollView) self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) + + 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.file, strongSelf, rect, gesture, true) + } } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + private func openGifContextMenu(file: TelegramMediaFile, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { + guard let component = self.component else { + return + } + component.inputInteraction.openGifContextMenu(file, 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[item.file.fileId] { @@ -432,6 +468,18 @@ public final class GifPagerContentComponent: Component { 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) { + return (itemLayer.item, itemLayer) + } + } + + return nil + } + private var previousScrollingOffset: CGFloat? public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { @@ -600,4 +648,3 @@ public final class GifPagerContentComponent: Component { return view.update(component: self, availableSize: availableSize, state: state, environment: environment, transition: transition) } } - diff --git a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift index a3f4e96a63..0a738c851f 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift +++ b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift @@ -26,3 +26,9 @@ public func cacheLottieAnimation(data: Data, width: Int, height: Int, writer: An writer.finish() } } + +public func cacheStillSticker(path: String, width: Int, height: Int, writer: AnimationCacheItemWriter) { + writer.queue.async { + 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..35a1806d35 --- /dev/null +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal @@ -0,0 +1,38 @@ +#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 texture[[texture(0)]] +) { + constexpr sampler s(address::clamp_to_edge, filter::linear); + return half4(texture.sample(s, in.texCoord)); +} diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift new file mode 100644 index 0000000000..2a3646512d --- /dev/null +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift @@ -0,0 +1,767 @@ +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 { + let width: Int + let height: Int + + private var items: [TextureStorage.Content] = [] + + init(width: Int, height: Int) { + self.width = width + self.height = height + } + + func recycle(content: TextureStorage.Content) { + if self.items.count < 4 { + self.items.append(content) + } else { + print("Warning: over-recycling texture storage") + } + } + + func take(device: MTLDevice) -> TextureStorage.Content? { + if self.items.isEmpty { + guard let content = TextureStorage.Content(device: device, width: self.width, height: self.height) else { + return nil + } + return content + } + return self.items.removeLast() + } + } + + private final class TextureStorage { + final class Content { + let buffer: MTLBuffer? + + let width: Int + let height: Int + let bytesPerRow: Int + let texture: MTLTexture + + init?(device: MTLDevice, width: Int, height: Int) { + let bytesPerPixel = 4 + let pixelRowAlignment = device.minimumLinearTextureAlignment(for: .bgra8Unorm) + 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 = .bgra8Unorm + textureDescriptor.width = width + textureDescriptor.height = height + textureDescriptor.usage = [.renderTarget] + 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 = .bgra8Unorm + textureDescriptor.width = width + textureDescriptor.height = height + textureDescriptor.usage = [.renderTarget] + 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, range: Range, 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 { + rgbaData.withUnsafeBytes { bytes in + let _ = memcpy(buffer.contents(), bytes.baseAddress!.advanced(by: range.lowerBound), bytesPerRow * height) + } + } else { + rgbaData.withUnsafeBytes { bytes in + self.texture.replace(region: region, mipmapLevel: 0, withBytes: bytes.baseAddress!.advanced(by: range.lowerBound), 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) + } + } + + /*func createCGImage() -> CGImage? { + if self.isInvalidated { + return nil + } + self.isInvalidated = true + + #if targetEnvironment(simulator) + guard let data = NSMutableData(capacity: self.content.bytesPerRow * self.content.height) else { + return nil + } + data.length = self.content.bytesPerRow * self.content.height + self.content.texture.getBytes(data.mutableBytes, bytesPerRow: self.content.bytesPerRow, bytesPerImage: self.content.bytesPerRow * self.content.height, from: MTLRegion(origin: MTLOrigin(), size: MTLSize(width: self.content.width, height: self.content.height, depth: 1)), mipmapLevel: 0, slice: 0) + + guard let dataProvider = CGDataProvider(data: data as CFData) else { + return nil + } + #else + let content = self.content + let pool = self.pool + guard let dataProvider = CGDataProvider(data: Data(bytesNoCopy: self.content.buffer.contents(), count: self.content.buffer.length, deallocator: .custom { [weak pool] _, _ in + guard let pool = pool else { + return + } + pool.recycle(content: content) + }) as CFData) else { + return nil + } + #endif + + guard let image = CGImage( + width: Int(self.content.width), + height: Int(self.content.height), + bitsPerComponent: 8, + bitsPerPixel: 8 * 4, + bytesPerRow: self.content.bytesPerRow, + space: DeviceGraphicsContextSettings.shared.colorSpace, + bitmapInfo: DeviceGraphicsContextSettings.shared.transparentBitmapInfo, + provider: dataProvider, + decode: nil, + shouldInterpolate: true, + intent: .defaultIntent + ) else { + return nil + } + + return image + }*/ + } + + private final class Frame { + let timestamp: Double + let texture: TextureStorage.Content + + init(device: MTLDevice, texture: TextureStorage.Content, data: AnimationCacheItemFrame, timestamp: Double) { + self.timestamp = timestamp + self.texture = texture + + switch data.format { + case let .rgba(width, height, bytesPerRow): + texture.replace(rgbaData: data.data, range: data.range, width: width, height: height, bytesPerRow: 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 timestamp: Double = 0.0 + 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 + + init(slotIndex: Int, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { + self.slotIndex = slotIndex + 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, texturePool: TextureStoragePool, advanceTimestamp: Double) -> LoadFrameTask? { + return self.update(device: device, texturePool: texturePool, advanceTimestamp: advanceTimestamp) + } + + private func update(device: MTLDevice, texturePool: TextureStoragePool, advanceTimestamp: Double?) -> LoadFrameTask? { + guard let item = self.item else { + return nil + } + + let timestamp = self.timestamp + if let advanceTimestamp = advanceTimestamp { + self.timestamp += advanceTimestamp + } + + if let currentFrame = self.currentFrame, currentFrame.timestamp == self.timestamp { + } else if !self.isLoadingFrame { + self.isLoadingFrame = true + + return LoadFrameTask(task: { [weak self] in + let frame = item.getFrame(at: timestamp) + + return { + guard let strongSelf = self else { + return + } + + var currentFrame: Frame? + let texture = texturePool.take(device: device) + if let frame = frame, let texture = texture { + currentFrame = Frame(device: device, texture: texture, data: frame, timestamp: timestamp) + } + + 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 texturePool: TextureStoragePool + + 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 + + self.slotsX = 16 + self.slotsY = 16 + 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.texturePool = TextureStoragePool(width: Int(self.cellSize.width), height: Int(self.cellSize.height)) + + 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 + } + + 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, 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)) + 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 itemContext] in + Queue.mainQueue().async { + guard let strongSelf = self, let currentItemContext = strongSelf.itemContexts[itemId], currentItemContext === itemContext else { + return + } + if let index = currentItemContext.targets.firstIndex(where: { $0.id == targetId }) { + currentItemContext.targets.remove(at: index) + if currentItemContext.targets.isEmpty { + strongSelf.slotToItemId[currentItemContext.slotIndex] = nil + strongSelf.itemContexts.removeValue(forKey: itemId) + + if strongSelf.itemContexts.isEmpty { + strongSelf.isPlaying = false + } + } + } + } + } + } else { + return nil + } + } + + 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, texturePool: self.texturePool, advanceTimestamp: advanceTimestamp) { + tasks.append(task) + } + } + } + + return tasks + } + + func redraw() { + guard let commandBuffer = self.commandQueue.makeCommandBuffer() else { + return + } + guard let drawable = self.nextDrawable() 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: [MultiAnimationMetalRendererImpl.TextureStorage.Content] = [] + + 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(self.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(self.cellSize.width), UInt32(self.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 * 0 + 0] = Float(contentsRect.minX).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + vertices[4 * 0 + 1] = Float(contentsRect.minY).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.minY).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) + + 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.maxY).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.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(frame.texture) + renderEncoder.setFragmentTexture(frame.texture.texture, index: 0) + + 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 _ in usedTextures { + } + } + } + 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.activeProcessorCount > 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(groupId: String, 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(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { + return false + } + + public func loadFirstFrame(groupId: String, 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 3354285be9..6b354caa28 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -11,7 +11,11 @@ public protocol MultiAnimationRenderer: AnyObject { func loadFirstFrame(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable } +private var nextRenderTargetId: Int64 = 1 + open class MultiAnimationRenderTarget: SimpleLayer { + public let id: Int64 + fileprivate let deinitCallbacks = Bag<() -> Void>() fileprivate let updateStateCallbacks = Bag<() -> Void>() @@ -25,6 +29,29 @@ open class MultiAnimationRenderTarget: SimpleLayer { } } + 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() @@ -369,7 +396,8 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - private let firstFrameQueue: Queue + public static let firstFrameQueue = Queue(name: "MultiAnimationRenderer-FirstFrame", qos: .userInteractive) + private var groupContexts: [String: GroupContext] = [:] private var frameSkip: Int private var displayLink: ConstantDisplayLinkAnimator? @@ -399,8 +427,6 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } public init() { - self.firstFrameQueue = Queue(name: "MultiAnimationRenderer-FirstFrame", qos: .userInteractive) - if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.activeProcessorCount > 2 { self.frameSkip = 1 } else { @@ -413,7 +439,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { if let current = self.groupContexts[groupId] { groupContext = current } else { - groupContext = GroupContext(firstFrameQueue: self.firstFrameQueue, stateUpdated: { [weak self] in + groupContext = GroupContext(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -434,7 +460,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { if let current = self.groupContexts[groupId] { groupContext = current } else { - groupContext = GroupContext(firstFrameQueue: self.firstFrameQueue, stateUpdated: { [weak self] in + groupContext = GroupContext(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -451,7 +477,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { if let current = self.groupContexts[groupId] { groupContext = current } else { - groupContext = GroupContext(firstFrameQueue: self.firstFrameQueue, stateUpdated: { [weak self] in + groupContext = GroupContext(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -475,14 +501,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { self.isPlaying = isPlaying } - private var previousTimestamp: Double? - private func animationTick() { - let timestamp = CFAbsoluteTimeGetCurrent() - if let _ = self.previousTimestamp { - } - self.previousTimestamp = timestamp - let secondsPerFrame = Double(self.frameSkip) / 60.0 var tasks: [LoadFrameGroupTask] = [] diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index 724c187b04..d0809698b0 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -45,17 +45,20 @@ public final class TextNodeWithEntities { 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 + placeholderColor: UIColor, + attemptSynchronous: Bool ) { self.context = context self.cache = cache self.renderer = renderer self.placeholderColor = placeholderColor + self.attemptSynchronous = attemptSynchronous } } @@ -115,7 +118,7 @@ public final class TextNodeWithEntities { if let maybeNode = maybeNode { if let applyArguments = applyArguments { - maybeNode.updateInlineStickers(context: applyArguments.context, cache: applyArguments.cache, renderer: applyArguments.renderer, textLayout: layout, placeholderColor: applyArguments.placeholderColor) + maybeNode.updateInlineStickers(context: applyArguments.context, cache: applyArguments.cache, renderer: applyArguments.renderer, textLayout: layout, placeholderColor: applyArguments.placeholderColor, attemptSynchronousLoad: false) } return maybeNode @@ -123,7 +126,7 @@ public final class TextNodeWithEntities { 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) + resultNode.updateInlineStickers(context: applyArguments.context, cache: applyArguments.cache, renderer: applyArguments.renderer, textLayout: layout, placeholderColor: applyArguments.placeholderColor, attemptSynchronousLoad: false) } return resultNode @@ -140,7 +143,7 @@ public final class TextNodeWithEntities { } } - private func updateInlineStickers(context: AccountContext, cache: AnimationCache, renderer: MultiAnimationRenderer, textLayout: TextNodeLayout?, placeholderColor: UIColor) { + private func updateInlineStickers(context: AccountContext, cache: AnimationCache, renderer: MultiAnimationRenderer, textLayout: TextNodeLayout?, placeholderColor: UIColor, attemptSynchronousLoad: Bool) { var nextIndexById: [Int64: Int] = [:] var validIds: [InlineStickerItemLayer.Key] = [] @@ -165,7 +168,7 @@ public final class TextNodeWithEntities { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: attemptSynchronousLoad, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) self.inlineStickerItemLayers[id] = itemLayer self.textNode.layer.addSublayer(itemLayer) 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/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/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index a05f8bdb55..ae95ba6acc 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -3403,7 +3403,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() } @@ -8002,7 +8002,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 @@ -8011,7 +8011,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) @@ -12484,7 +12484,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) } @@ -16109,7 +16109,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/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index fbe73c17ca..fae7867aee 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2022,7 +2022,13 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } } - private let emptyInputView = UIView() + 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: diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index fbf1eca0c6..64aa27d3e5 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -15,6 +15,33 @@ import ComponentDisplayAdapters import SettingsUI import TextFormat import PagerComponent +import AppBundle +import PremiumUI +import AudioToolbox +import UndoUI +import ContextUI +import GalleryUI + +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 ChatEntityKeyboardInputNode: ChatInputNode { struct InputData: Equatable { @@ -40,29 +67,70 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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 emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak interfaceInteraction] item, _, _, _ in - guard let interfaceInteraction = interfaceInteraction else { - return - } - var text = "." - var emojiAttribute: ChatTextInputTextCustomEmojiAttribute? - loop: for attribute in item.file.attributes { - switch attribute { - case let .Sticker(displayText, packReference, _): - text = displayText - if let packReference = packReference { - emojiAttribute = ChatTextInputTextCustomEmojiAttribute(stickerPack: packReference, fileId: item.file.fileId.id, file: item.file) - break loop - } - default: - break + performItemAction: { [weak interfaceInteraction, weak controllerInteraction] item, _, _, _ in + let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in + guard let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { + return } - } - - if let emojiAttribute = emojiAttribute { - interfaceInteraction.insertText(NSAttributedString(string: text, attributes: [ChatTextInputAttributes.customEmoji: emojiAttribute])) - } + + 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 { + //TODO:localize + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { [weak controllerInteraction] in + guard let controllerInteraction = controllerInteraction else { + return + } + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: context, subject: .premiumStickers, action: { + let controller = PremiumIntroScreen(context: context, source: .stickers) + 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: false, action: { _ in return false }), 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 { @@ -72,6 +140,13 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }, openStickerSettings: { }, + openPremiumSection: { [weak controllerInteraction] in + guard let controllerInteraction = controllerInteraction else { + return + } + let controller = PremiumIntroScreen(context: context, source: .stickers) + controllerInteraction.navigationController()?.pushViewController(controller) + }, pushController: { [weak controllerInteraction] controller in guard let controllerInteraction = controllerInteraction else { return @@ -103,10 +178,20 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { ) let stickerInputInteraction = EmojiPagerContentComponent.InputInteraction( performItemAction: { [weak interfaceInteraction] item, view, rect, layer in - guard let interfaceInteraction = interfaceInteraction else { - return - } - let _ = interfaceInteraction.sendSticker(.standalone(media: item.file), false, view, rect, layer) + let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in + guard let interfaceInteraction = interfaceInteraction else { + return + } + if let file = item.file { + 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 { @@ -122,6 +207,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { controller.navigationPresentation = .modal controllerInteraction.navigationController()?.pushViewController(controller) }, + openPremiumSection: { + }, pushController: { [weak controllerInteraction] controller in guard let controllerInteraction = controllerInteraction else { return @@ -157,31 +244,52 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return } let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) + }, + openGifContextMenu: { _, _, _, _, _ in } ) let animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { return TempBox.shared.tempFile(fileName: "file").path }) - let animationRenderer = MultiAnimationRendererImpl() + let animationRenderer: MultiAnimationRenderer + /*if #available(iOS 13.0, *) { + animationRenderer = MultiAnimationMetalRendererImpl() + } else {*/ + animationRenderer = MultiAnimationRendererImpl() + //} let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] - let emojiItems: Signal = context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000) - |> map { view -> EmojiPagerContentComponent in + let emojiItems: Signal = combineLatest( + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + hasPremium + ) + |> map { view, hasPremium -> EmojiPagerContentComponent in struct ItemGroup { + var supergroupId: AnyHashable var id: AnyHashable + var isPremium: Bool var items: [EmojiPagerContentComponent.Item] } var itemGroups: [ItemGroup] = [] var itemGroupIndexById: [AnyHashable: Int] = [:] - var emojiCollectionIds = Set() - for (id, info, _) in view.collectionInfos { - if let info = info as? StickerPackCollectionInfo { - if info.shortName.lowercased().contains("emoji") { - emojiCollectionIds.insert(id) + 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, isPremium: false, items: [resultItem])) } } } @@ -190,22 +298,28 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let item = entry.item as? StickerPackItem else { continue } - if item.file.isAnimatedSticker || item.file.isVideoSticker { - if emojiCollectionIds.contains(entry.index.collectionId) { - let resultItem = EmojiPagerContentComponent.Item( - emoji: "", - file: item.file, - stickerPackItem: nil - ) - - let groupId = entry.index.collectionId - if let groupIndex = itemGroupIndexById[groupId] { - itemGroups[groupIndex].items.append(resultItem) - } else { - itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) - } - } + let resultItem = EmojiPagerContentComponent.Item( + file: item.file, + staticEmoji: nil, + subgroupId: nil + ) + + let supergroupId = entry.index.collectionId + let groupId: AnyHashable = supergroupId + let isPremium: Bool = item.file.isPremiumEmoji && !hasPremium + if isPremium && isPremiumDisabled { + continue + } + /*if isPremium { + groupId = "\(supergroupId)-p" + } else { + groupId = supergroupId + }*/ + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, isPremium: isPremium, items: [resultItem])) } } @@ -229,28 +343,21 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - return EmojiPagerContentComponent.ItemGroup(id: group.id, title: title, items: group.items) + return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: title, isPremium: group.isPremium, displayPremiumBadges: false, items: group.items) }, itemLayoutType: .compact ) } - 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 stickerItems: Signal = combineLatest( context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000), hasPremium ) |> map { view, hasPremium -> EmojiPagerContentComponent in struct ItemGroup { + var supergroupId: AnyHashable var id: AnyHashable + var displayPremiumBadges: Bool var items: [EmojiPagerContentComponent.Item] } var itemGroups: [ItemGroup] = [] @@ -282,9 +389,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } let resultItem = EmojiPagerContentComponent.Item( - emoji: "", file: item.file, - stickerPackItem: nil + staticEmoji: nil, + subgroupId: nil ) let groupId = "saved" @@ -292,7 +399,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: false, items: [resultItem])) } } } @@ -308,9 +415,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } let resultItem = EmojiPagerContentComponent.Item( - emoji: "", file: item.media, - stickerPackItem: nil + staticEmoji: nil, + subgroupId: nil ) let groupId = "recent" @@ -318,7 +425,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: false, items: [resultItem])) } count += 1 @@ -357,9 +464,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { processedIds.insert(item.media.fileId) let resultItem = EmojiPagerContentComponent.Item( - emoji: "", file: item.media, - stickerPackItem: nil + staticEmoji: nil, + subgroupId: nil ) let groupId = "premium" @@ -367,7 +474,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: false, items: [resultItem])) } } } @@ -377,16 +484,16 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { continue } let resultItem = EmojiPagerContentComponent.Item( - emoji: "", file: item.file, - stickerPackItem: item + staticEmoji: nil, + subgroupId: nil ) let groupId = entry.index.collectionId if let groupIndex = itemGroupIndexById[groupId] { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(id: groupId, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: true, items: [resultItem])) } } @@ -416,7 +523,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - return EmojiPagerContentComponent.ItemGroup(id: group.id, title: title, items: group.items) + return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: title, isPremium: false, displayPremiumBadges: group.displayPremiumBadges, items: group.items) }, itemLayoutType: .detailed ) @@ -599,6 +706,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return } let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) + }, + openGifContextMenu: { [weak self] file, sourceView, sourceRect, gesture, isSaved in + guard let strongSelf = self else { + return + } + strongSelf.openGifContextMenu(file: file, sourceView: sourceView, sourceRect: sourceRect, gesture: gesture, isSaved: isSaved) } ) @@ -790,4 +903,163 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return (expandedHeight, 0.0) } + + private func openGifContextMenu(file: TelegramMediaFile, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { + let canSaveGif: Bool + if 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 (_, _, _, _, _, _, _, _, interfaceState, _, _, _) = strongSelf.validLayout { + 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: strongSelf.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: strongSelf.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) + } + } } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index 9d952b1199..2ee0280fba 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -1642,7 +1642,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 +1651,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) @@ -1795,7 +1795,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 +1804,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) @@ -2725,7 +2725,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/ChatMessageActionItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift index 3cd58a48c5..2a9c0d613c 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift @@ -278,7 +278,8 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { context: item.context, cache: item.controllerInteraction.presentationContext.animationCache, renderer: item.controllerInteraction.presentationContext.animationRenderer, - placeholderColor: item.presentationData.theme.theme.chat.message.freeform.withWallpaper.reactionInactiveBackground + 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) diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index cf292275b6..c212d171e9 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -975,7 +975,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? @@ -1145,7 +1145,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) @@ -1308,7 +1308,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) diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 20e0337914..7f7efef8c2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -301,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 } } @@ -1035,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: (ChatMessageReplyInfoNode.Arguments) -> (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)), @@ -1691,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 }) @@ -1809,7 +1817,7 @@ class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewItemNode animationCache: item.controllerInteraction.presentationContext.animationCache, animationRenderer: item.controllerInteraction.presentationContext.animationRenderer )) - replyInfoSizeApply = (sizeAndApply.0, { sizeAndApply.1() }) + 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) @@ -2283,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)]?, @@ -2489,7 +2497,7 @@ 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 { diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index 1034a9c0a5..b9e933d3f8 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift @@ -393,7 +393,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? @@ -580,7 +580,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) @@ -706,7 +706,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/ChatMessageReplyInfoNode.swift b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift index 4e6f278640..ac2d2e9950 100644 --- a/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageReplyInfoNode.swift @@ -90,7 +90,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode { self.contentNode.addSubnode(self.lineNode) } - class func asyncLayout(_ maybeNode: ChatMessageReplyInfoNode?) -> (_ arguments: Arguments) -> (CGSize, () -> ChatMessageReplyInfoNode) { + class func asyncLayout(_ maybeNode: ChatMessageReplyInfoNode?) -> (_ arguments: Arguments) -> (CGSize, (Bool) -> ChatMessageReplyInfoNode) { let titleNodeLayout = TextNode.asyncLayout(maybeNode?.titleNode) let textNodeLayout = TextNodeWithEntities.asyncLayout(maybeNode?.textNode) let imageNodeLayout = TransformImageNode.asyncLayout(maybeNode?.imageNode) @@ -267,7 +267,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode { 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 @@ -283,7 +283,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode { let titleNode = titleApply() 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) + 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 diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 941f83c408..1b79c9be75 100644 --- a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift @@ -526,7 +526,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) @@ -762,7 +762,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 { @@ -892,7 +892,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) diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index d095151145..6d1a5550fe 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -249,6 +249,10 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } } + + if let updatingMedia = item.attributes.updatingMedia { + messageEntities = updatingMedia.entities?.entities ?? [] + } } var entities: [MessageTextEntity]? @@ -404,7 +408,7 @@ 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 { @@ -432,7 +436,7 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { } } - let _ = textApply(TextNodeWithEntities.Arguments(context: item.context, cache: item.controllerInteraction.presentationContext.animationCache, renderer: item.controllerInteraction.presentationContext.animationRenderer, placeholderColor: messageTheme.mediaPlaceholderColor)) + 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 { diff --git a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index 59f7725103..cfb4bb135a 100644 --- a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift @@ -685,7 +685,8 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { context: strongSelf.context, cache: cache, renderer: renderer, - placeholderColor: theme.list.mediaPlaceholderColor + placeholderColor: theme.list.mediaPlaceholderColor, + attemptSynchronous: false ) } let _ = textApply(textArguments) diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 936cb29704..2d57f94a97 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -898,7 +898,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/ChatSearchResultsContollerNode.swift b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift index ec4bbb20e1..e9a78f14e5 100644 --- a/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift +++ b/submodules/TelegramUI/Sources/ChatSearchResultsContollerNode.swift @@ -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/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 889de57d64..f7de318cab 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -34,6 +34,7 @@ private let counterFont = Font.with(size: 14.0, design: .regular, traits: [.mono private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { private var item: ChatTextInputAccessoryItem private var theme: PresentationTheme + private var strings: PresentationStrings private var width: CGFloat private let iconImageNode: ASImageNode private var animationView: ComponentView? @@ -42,6 +43,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { init(item: ChatTextInputAccessoryItem, theme: PresentationTheme, strings: PresentationStrings) { self.item = item self.theme = theme + self.strings = strings self.iconImageNode = ASImageNode() @@ -89,6 +91,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { 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) @@ -156,6 +159,8 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { 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.iconImageNode.frame = imageFrame diff --git a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift index cdae308f0c..13b9d4aa81 100644 --- a/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift +++ b/submodules/TelegramUI/Sources/FeaturedStickersScreen.swift @@ -500,7 +500,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 +509,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) @@ -588,7 +588,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 +597,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) diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index 8eeca26f7b..f9edf19c44 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -191,7 +191,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 +200,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) diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index 4cac521101..c9a9869dd1 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -143,7 +143,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 +152,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) diff --git a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift index cd1c1377ac..01190bea8b 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -163,7 +163,7 @@ 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? 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/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 8dc1c40b17..d1df4d63e6 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -8545,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/ReplyAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift index 3d9e461324..a80f41176a 100644 --- a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift @@ -76,7 +76,8 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { context: context, cache: animationCache, renderer: animationRenderer, - placeholderColor: theme.list.mediaPlaceholderColor + placeholderColor: theme.list.mediaPlaceholderColor, + attemptSynchronous: false ) } diff --git a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index 1de8bf6eda..eb919dbc49 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -147,7 +147,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 +156,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) 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/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..6a9a9ab381 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -628,7 +628,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 @@ -885,7 +885,7 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { } else { self.isUserInteractionEnabled = false } - case let .sticker(_, _, _, _, undoText): + case let .sticker(_, _, _, _, undoText, _): self.isUserInteractionEnabled = undoText != nil case .dice: self.panelWrapperNode.clipsToBounds = true @@ -963,7 +963,14 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { } @objc private func undoButtonPressed() { - let _ = self.action(.undo) + switch self.content { + case let .sticker(_, _, _, _, _, customAction): + if let customAction = customAction { + customAction() + } + 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/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] } From 74b5d4998c77b4b0d01dc44bea30449315c2f4b2 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 01:44:51 +0200 Subject: [PATCH 045/113] Support static emoji --- .../Sources/EmojiTextAttachmentView.swift | 61 ++++++++++++------- .../Components/LottieAnimationCache/BUILD | 1 + .../Sources/LottieAnimationCache.swift | 13 ++++ 3 files changed, 54 insertions(+), 21 deletions(-) diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index e22da66af9..f0b417afcf 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -163,32 +163,51 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } let context = self.context - self.disposable = renderer.add(groupId: self.groupId, 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.isAnimatedSticker || file.isVideoEmoji { + self.disposable = renderer.add(groupId: self.groupId, 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) - 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() + let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in + guard let result = result else { return } - cacheLottieAnimation(data: data, width: Int(size.width), height: Int(size.height), writer: writer) + + 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() } }) - - 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(groupId: self.groupId, 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() + } + }) + } } } 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 0a738c851f..85ef713466 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift +++ b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift @@ -4,6 +4,7 @@ import AnimationCache import Display import RLottieBinding import GZip +import WebPBinding public func cacheLottieAnimation(data: Data, width: Int, height: Int, writer: AnimationCacheItemWriter) { writer.queue.async { @@ -29,6 +30,18 @@ public func cacheLottieAnimation(data: Data, width: Int, height: Int, writer: An 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.withContext { 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) + }, proposedWidth: width, proposedHeight: height, duration: 1.0) + } + writer.finish() } } From c5d3e5e2945c5f5301ef1639e829d960f8f565a4 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 11:23:09 +0200 Subject: [PATCH 046/113] Temp --- .../Sources/AnimationCache.swift | 92 +++++++--- .../Sources/EmojiTextAttachmentView.swift | 3 +- .../MultiAnimationRendererShaders.metal | 5 +- .../Sources/MultiAnimationMetalRenderer.swift | 165 +++++++++++++----- .../Sources/MultiAnimationRenderer.swift | 14 +- .../Sources/ChatMessageBubbleItemNode.swift | 6 +- 6 files changed, 206 insertions(+), 79 deletions(-) diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index f92e1ef1f4..96920e9871 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -6,18 +6,34 @@ import ManagedFile import Compression public final class AnimationCacheItemFrame { - public enum Format { - case rgba(width: Int, height: Int, bytesPerRow: Int) + public enum RequestedFormat { + case rgba + case yuva + } + + 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 } @@ -25,22 +41,22 @@ public final class AnimationCacheItemFrame { public final class AnimationCacheItem { public let numFrames: Int - private let getFrameImpl: (Int) -> AnimationCacheItemFrame? + private let getFrameImpl: (Int, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? private let getFrameIndexImpl: (Double) -> Int - public init(numFrames: Int, getFrame: @escaping (Int) -> AnimationCacheItemFrame?, getFrameIndexImpl: @escaping (Double) -> Int) { + public init(numFrames: Int, getFrame: @escaping (Int, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame?, getFrameIndexImpl: @escaping (Double) -> Int) { self.numFrames = numFrames self.getFrameImpl = getFrame self.getFrameIndexImpl = getFrameIndexImpl } - public func getFrame(index: Int) -> AnimationCacheItemFrame? { - return self.getFrameImpl(index) + public func getFrame(index: Int, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { + return self.getFrameImpl(index, requestedFormat) } - public func getFrame(at duration: Double) -> AnimationCacheItemFrame? { + public func getFrame(at duration: Double, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { let index = self.getFrameIndexImpl(duration) - return self.getFrameImpl(index) + return self.getFrameImpl(index, requestedFormat) } } @@ -495,13 +511,11 @@ private final class AnimationCacheItemAccessor { self.currentDctCoefficients = DctCoefficientsYUVA420(width: width, height: height) } - func getFrame(index: Int) -> AnimationCacheItemFrame? { + func getFrame(index: Int, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { guard let frameInfo = self.frameMapping[index] else { return nil } - let currentSurface = ImageARGB(width: self.currentYUVASurface.yPlane.width, height: self.currentYUVASurface.yPlane.height) - var frameDataOffset = 0 let frameLength = frameInfo.range.upperBound - frameInfo.range.lowerBound for i in 0 ..< 4 { @@ -531,9 +545,47 @@ private final class AnimationCacheItemAccessor { } self.currentDctCoefficients.idct(dctData: self.currentDctData, target: self.currentYUVASurface) - self.currentYUVASurface.toARGB(target: currentSurface) - return AnimationCacheItemFrame(data: currentSurface.argbPlane.data, range: 0 ..< currentSurface.argbPlane.data.count, format: .rgba(width: currentSurface.argbPlane.width, height: currentSurface.argbPlane.height, bytesPerRow: currentSurface.argbPlane.bytesPerRow), duration: frameInfo.duration) + switch requestedFormat { + case .rgba: + let currentSurface = ImageARGB(width: self.currentYUVASurface.yPlane.width, height: self.currentYUVASurface.yPlane.height) + self.currentYUVASurface.toARGB(target: currentSurface) + + return AnimationCacheItemFrame(format: .rgba(data: currentSurface.argbPlane.data, width: currentSurface.argbPlane.width, height: currentSurface.argbPlane.height, bytesPerRow: currentSurface.argbPlane.bytesPerRow), duration: frameInfo.duration) + case .yuva: + let currentYUVASurface = self.currentYUVASurface + self.currentYUVASurface = ImageYUVA420(width: currentYUVASurface.yPlane.width, height: currentYUVASurface.yPlane.height) + + return AnimationCacheItemFrame( + format: .yuva( + y: AnimationCacheItemFrame.Plane( + data: currentYUVASurface.yPlane.data, + width: currentYUVASurface.yPlane.width, + height: currentYUVASurface.yPlane.height, + bytesPerRow: currentYUVASurface.yPlane.bytesPerRow + ), + u: AnimationCacheItemFrame.Plane( + data: currentYUVASurface.uPlane.data, + width: currentYUVASurface.uPlane.width, + height: currentYUVASurface.uPlane.height, + bytesPerRow: currentYUVASurface.uPlane.bytesPerRow + ), + v: AnimationCacheItemFrame.Plane( + data: currentYUVASurface.vPlane.data, + width: currentYUVASurface.vPlane.width, + height: currentYUVASurface.vPlane.height, + bytesPerRow: currentYUVASurface.vPlane.bytesPerRow + ), + a: AnimationCacheItemFrame.Plane( + data: currentYUVASurface.aPlane.data, + width: currentYUVASurface.aPlane.width, + height: currentYUVASurface.aPlane.height, + bytesPerRow: currentYUVASurface.aPlane.bytesPerRow + ) + ), + duration: frameInfo.duration + ) + } } func getFrameIndex(duration: Double) -> Int { @@ -675,8 +727,8 @@ private func loadItem(path: String) -> AnimationCacheItem? { let itemAccessor = AnimationCacheItemAccessor(data: data, frameMapping: frameMapping, width: Int(width), height: Int(height), dctQuality: Int(dctQuality)) - return AnimationCacheItem(numFrames: Int(numFrames), getFrame: { index in - return itemAccessor.getFrame(index: index) + return AnimationCacheItem(numFrames: Int(numFrames), getFrame: { index, requestedFormat in + return itemAccessor.getFrame(index: index, requestedFormat: requestedFormat) }, getFrameIndexImpl: { duration in return itemAccessor.getFrameIndex(duration: duration) }) diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index f0b417afcf..90f7314679 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -101,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 } diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal b/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal index 35a1806d35..c8a7c8c2f7 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal @@ -31,7 +31,10 @@ vertex Varyings multiAnimationVertex( fragment half4 multiAnimationFragment( Varyings in[[stage_in]], - texture2d texture[[texture(0)]] + 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); return half4(texture.sample(s, in.texCoord)); diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift index 2a3646512d..0f9e39af6d 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift @@ -64,12 +64,14 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { private final class TextureStoragePool { let width: Int let height: Int + let format: TextureStorage.Content.Format private var items: [TextureStorage.Content] = [] - init(width: Int, height: Int) { + init(width: Int, height: Int, format: TextureStorage.Content.Format) { self.width = width self.height = height + self.format = format } func recycle(content: TextureStorage.Content) { @@ -82,7 +84,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { func take(device: MTLDevice) -> TextureStorage.Content? { if self.items.isEmpty { - guard let content = TextureStorage.Content(device: device, width: self.width, height: self.height) else { + guard let content = TextureStorage.Content(device: device, width: self.width, height: self.height, format: format) else { return nil } return content @@ -93,6 +95,11 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { private final class TextureStorage { final class Content { + enum Format { + case bgra + case r + } + let buffer: MTLBuffer? let width: Int @@ -100,9 +107,18 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { let bytesPerRow: Int let texture: MTLTexture - init?(device: MTLDevice, width: Int, height: Int) { - let bytesPerPixel = 4 - let pixelRowAlignment = device.minimumLinearTextureAlignment(for: .bgra8Unorm) + 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 = device.minimumLinearTextureAlignment(for: pixelFormat) let bytesPerRow = alignUp(size: width * bytesPerPixel, align: pixelRowAlignment) self.width = width @@ -112,7 +128,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { #if targetEnvironment(simulator) let textureDescriptor = MTLTextureDescriptor() textureDescriptor.textureType = .type2D - textureDescriptor.pixelFormat = .bgra8Unorm + textureDescriptor.pixelFormat = pixelFormat textureDescriptor.width = width textureDescriptor.height = height textureDescriptor.usage = [.renderTarget] @@ -130,7 +146,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { let textureDescriptor = MTLTextureDescriptor() textureDescriptor.textureType = .type2D - textureDescriptor.pixelFormat = .bgra8Unorm + textureDescriptor.pixelFormat = pixelFormat textureDescriptor.width = width textureDescriptor.height = height textureDescriptor.usage = [.renderTarget] @@ -144,7 +160,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.texture = texture } - func replace(rgbaData: Data, range: Range, width: Int, height: Int, bytesPerRow: Int) { + 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 @@ -153,11 +169,11 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { if let buffer = self.buffer, self.bytesPerRow == bytesPerRow { rgbaData.withUnsafeBytes { bytes in - let _ = memcpy(buffer.contents(), bytes.baseAddress!.advanced(by: range.lowerBound), bytesPerRow * height) + let _ = memcpy(buffer.contents(), bytes.baseAddress!, bytesPerRow * height) } } else { rgbaData.withUnsafeBytes { bytes in - self.texture.replace(region: region, mipmapLevel: 0, withBytes: bytes.baseAddress!.advanced(by: range.lowerBound), bytesPerRow: bytesPerRow) + self.texture.replace(region: region, mipmapLevel: 0, withBytes: bytes.baseAddress!, bytesPerRow: bytesPerRow) } } } @@ -229,15 +245,26 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { private final class Frame { let timestamp: Double - let texture: TextureStorage.Content + let textureY: TextureStorage.Content + let textureU: TextureStorage.Content + let textureV: TextureStorage.Content + let textureA: TextureStorage.Content - init(device: MTLDevice, texture: TextureStorage.Content, data: AnimationCacheItemFrame, timestamp: Double) { + init?(device: MTLDevice, textureY: TextureStorage.Content, textureU: TextureStorage.Content, textureV: TextureStorage.Content, textureA: TextureStorage.Content, data: AnimationCacheItemFrame, timestamp: Double) { self.timestamp = timestamp - self.texture = texture + self.textureY = textureY + self.textureU = textureU + self.textureV = textureV + self.textureA = textureA switch data.format { - case let .rgba(width, height, bytesPerRow): - texture.replace(rgbaData: data.data, range: data.range, width: width, height: height, bytesPerRow: bytesPerRow) + case .rgba: + return nil + case let .yuva(y, u, v, a): + self.textureY.replace(rgbaData: y.data, width: y.width, height: y.height, bytesPerRow: y.bytesPerRow) + self.textureU.replace(rgbaData: u.data, width: u.width, height: u.height, bytesPerRow: u.bytesPerRow) + self.textureV.replace(rgbaData: v.data, width: v.width, height: v.height, bytesPerRow: v.bytesPerRow) + self.textureA.replace(rgbaData: a.data, width: a.width, height: a.height, bytesPerRow: a.bytesPerRow) } } } @@ -316,11 +343,11 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.isPlaying = isPlaying } - func animationTick(device: MTLDevice, texturePool: TextureStoragePool, advanceTimestamp: Double) -> LoadFrameTask? { - return self.update(device: device, texturePool: texturePool, advanceTimestamp: advanceTimestamp) + 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, texturePool: TextureStoragePool, advanceTimestamp: Double?) -> LoadFrameTask? { + private func update(device: MTLDevice, texturePoolFullPlane: TextureStoragePool, texturePoolHalfPlane: TextureStoragePool, advanceTimestamp: Double?) -> LoadFrameTask? { guard let item = self.item else { return nil } @@ -335,7 +362,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.isLoadingFrame = true return LoadFrameTask(task: { [weak self] in - let frame = item.getFrame(at: timestamp) + let frame = item.getFrame(at: timestamp, requestedFormat: .rgba) return { guard let strongSelf = self else { @@ -343,9 +370,12 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } var currentFrame: Frame? - let texture = texturePool.take(device: device) - if let frame = frame, let texture = texture { - currentFrame = Frame(device: device, texture: texture, data: frame, timestamp: timestamp) + let textureY = texturePoolFullPlane.take(device: device) + let textureU = texturePoolHalfPlane.take(device: device) + let textureV = texturePoolHalfPlane.take(device: device) + let textureA = texturePoolFullPlane.take(device: device) + 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, timestamp: timestamp) } strongSelf.isLoadingFrame = false @@ -369,7 +399,8 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { private let commandQueue: MTLCommandQueue private let renderPipelineState: MTLRenderPipelineState - private let texturePool: TextureStoragePool + private let texturePoolFullPlane: TextureStoragePool + private let texturePoolHalfPlane: TextureStoragePool private let slotCount: Int private let slotsX: Int @@ -389,8 +420,10 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.cellSize = cellSize self.stateUpdated = stateUpdated - self.slotsX = 16 - self.slotsY = 16 + 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)) @@ -413,7 +446,8 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.renderPipelineState = makePipelineState(device: self.metalDevice, library: defaultLibrary, vertexProgram: "multiAnimationVertex", fragmentProgram: "multiAnimationFragment")! - self.texturePool = TextureStoragePool(width: Int(self.cellSize.width), height: Int(self.cellSize.height)) + 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) super.init() @@ -427,6 +461,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.pixelFormat = .bgra8Unorm self.framebufferOnly = true self.allowsNextDrawableTimeout = true + self.isOpaque = false } override public init(layer: Any) { @@ -465,6 +500,23 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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 @@ -476,22 +528,18 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.isPlaying = true - return ActionDisposable { [weak self, weak itemContext] in + 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 index = currentItemContext.targets.firstIndex(where: { $0.id == targetId }) { - currentItemContext.targets.remove(at: index) - if currentItemContext.targets.isEmpty { - strongSelf.slotToItemId[currentItemContext.slotIndex] = nil - strongSelf.itemContexts.removeValue(forKey: itemId) - - if strongSelf.itemContexts.isEmpty { - strongSelf.isPlaying = false - } - } + + if let target = target { + target.deinitCallbacks.remove(deinitIndex) + target.updateStateCallbacks.remove(updateStateIndex) } + + strongSelf.removeTargetFromItemContext(itemId: itemId, itemContext: currentItemContext, targetId: targetId) } } } else { @@ -499,6 +547,21 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } } + 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 { @@ -515,7 +578,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { var tasks: [LoadFrameTask] = [] for (_, itemContext) in self.itemContexts { if itemContext.isPlaying { - if let task = itemContext.animationTick(device: self.metalDevice, texturePool: self.texturePool, advanceTimestamp: advanceTimestamp) { + if let task = itemContext.animationTick(device: self.metalDevice, texturePoolFullPlane: self.texturePoolFullPlane, texturePoolHalfPlane: self.texturePoolHalfPlane, advanceTimestamp: advanceTimestamp) { tasks.append(task) } } @@ -580,25 +643,31 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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 * 0 + 0] = Float(contentsRect.minX).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) - vertices[4 * 0 + 1] = Float(contentsRect.minY).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.minY).remap(fromLow: 0.0, fromHigh: 1.0, toLow: -1.0, toHigh: 1.0) - 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.maxY).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.maxY).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(frame.texture) - renderEncoder.setFragmentTexture(frame.texture.texture, index: 0) + usedTextures.append(frame.textureY) + usedTextures.append(frame.textureU) + usedTextures.append(frame.textureV) + usedTextures.append(frame.textureA) + renderEncoder.setFragmentTexture(frame.textureY.texture, index: 0) + renderEncoder.setFragmentTexture(frame.textureU.texture, index: 1) + renderEncoder.setFragmentTexture(frame.textureV.texture, index: 2) + renderEncoder.setFragmentTexture(frame.textureA.texture, index: 3) renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4, instanceCount: 1) } diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index 6b354caa28..c30fa0affe 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -16,8 +16,8 @@ private var nextRenderTargetId: Int64 = 1 open class MultiAnimationRenderTarget: SimpleLayer { public let id: Int64 - fileprivate let deinitCallbacks = Bag<() -> Void>() - fileprivate let updateStateCallbacks = Bag<() -> Void>() + let deinitCallbacks = Bag<() -> Void>() + let updateStateCallbacks = Bag<() -> Void>() public final var shouldBeAnimating: Bool = false { didSet { @@ -69,16 +69,16 @@ private final class FrameGroup { let timestamp: Double init?(item: AnimationCacheItem, timestamp: Double) { - guard let firstFrame = item.getFrame(at: timestamp) else { + guard let firstFrame = item.getFrame(at: timestamp, requestedFormat: .rgba) else { return nil } switch firstFrame.format { - case let .rgba(width, height, bytesPerRow): + 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) - firstFrame.data.withUnsafeBytes { bytes -> Void in - memcpy(context.bytes, bytes.baseAddress!.advanced(by: firstFrame.range.lowerBound), height * bytesPerRow) + data.withUnsafeBytes { bytes -> Void in + memcpy(context.bytes, bytes.baseAddress!, height * bytesPerRow) /*var sourceBuffer = vImage_Buffer() sourceBuffer.width = UInt(width) @@ -110,6 +110,8 @@ private final class FrameGroup { self.size = CGSize(width: CGFloat(width), height: CGFloat(height)) self.timestamp = timestamp self.badgeImage = nil + default: + return nil } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 7f7efef8c2..7b4bbe4d44 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -303,11 +303,11 @@ class ChatPresentationContext { }) let animationRenderer: MultiAnimationRenderer - /*if #available(iOS 13.0, *) { + if #available(iOS 13.0, *) { animationRenderer = MultiAnimationMetalRendererImpl() - } else {*/ + } else { animationRenderer = MultiAnimationRendererImpl() - //} + } self.animationRenderer = animationRenderer } From e70df961e1447c9028c9d103f78c32c930e638bf Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 11:39:55 +0200 Subject: [PATCH 047/113] Update API --- submodules/TelegramApi/Sources/Api0.swift | 7 +- submodules/TelegramApi/Sources/Api10.swift | 1436 +-- submodules/TelegramApi/Sources/Api11.swift | 1784 ++-- submodules/TelegramApi/Sources/Api12.swift | 1520 +-- submodules/TelegramApi/Sources/Api13.swift | 1576 ++- submodules/TelegramApi/Sources/Api14.swift | 2238 ++--- submodules/TelegramApi/Sources/Api15.swift | 2116 ++-- submodules/TelegramApi/Sources/Api16.swift | 1530 +-- submodules/TelegramApi/Sources/Api17.swift | 1696 ++-- submodules/TelegramApi/Sources/Api18.swift | 1684 ++-- submodules/TelegramApi/Sources/Api19.swift | 3932 ++------ submodules/TelegramApi/Sources/Api20.swift | 4578 ++++++--- submodules/TelegramApi/Sources/Api21.swift | 2292 +++-- submodules/TelegramApi/Sources/Api22.swift | 2160 ++-- submodules/TelegramApi/Sources/Api23.swift | 2156 ++-- submodules/TelegramApi/Sources/Api24.swift | 2342 +++-- submodules/TelegramApi/Sources/Api25.swift | 2380 ++--- submodules/TelegramApi/Sources/Api26.swift | 2396 +++-- submodules/TelegramApi/Sources/Api27.swift | 8658 +++-------------- submodules/TelegramApi/Sources/Api28.swift | 7510 ++++++++++++++ submodules/TelegramApi/Sources/Api8.swift | 178 +- submodules/TelegramApi/Sources/Api9.swift | 590 +- .../Sources/ApiUtils/TelegramMediaFile.swift | 2 + .../State/AccountStateManagementUtils.swift | 2 +- .../TelegramEngine/Payments/AppStore.swift | 2 +- .../Peers/UpdateCachedPeerData.swift | 2 +- .../Stickers/ImportStickers.swift | 2 +- .../Stickers/LoadedStickerPack.swift | 2 +- .../TelegramEngine/Stickers/StickerPack.swift | 4 +- .../Stickers/StickerSetInstallation.swift | 2 +- 30 files changed, 27416 insertions(+), 27361 deletions(-) create mode 100644 submodules/TelegramApi/Sources/Api28.swift diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 87f8a9b635..37050808eb 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -327,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) } @@ -344,11 +345,12 @@ 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[1147243133] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentGiftPremium($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) } @@ -588,6 +590,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) } @@ -705,7 +708,7 @@ 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[872932635] = { return Api.StickerSetCovered.parse_stickerSetMultiCovered($0) } dict[-1609668650] = { return Api.Theme.parse_theme($0) } diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index 8a78bc01fc..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,1051 +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 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 .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 .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 .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_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_messageActionGiftPremium(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - 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.MessageAction.messageActionGiftPremium(currency: _1!, amount: _2!, months: _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 7668430ca7..47642963ed 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -1,537 +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 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) + 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 .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) + 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 .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))]) + 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_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.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 @@ -541,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 @@ -613,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 91c4c76183..d25de327ff 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,404 +274,104 @@ 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) + 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? - _3 = parseString(reader) + if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - var _6: String? - _6 = parseString(reader) + 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 = _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!) + 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 @@ -501,417 +381,37 @@ public extension Api { } } public extension Api { - enum PremiumGiftOption: TypeConstructorDescription { - case premiumGiftOption(flags: Int32, months: Int32, currency: String, amount: Int64, botUrl: String, storeProduct: String?) + enum PaymentSavedCredentials: TypeConstructorDescription { + case paymentSavedCredentialsCard(id: String, title: 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): + case .paymentSavedCredentialsCard(let id, let title): if boxed { - buffer.appendInt32(1958953753) + buffer.appendInt32(-842892769) } - 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)} + serializeString(id, buffer: buffer, boxed: false) + serializeString(title, 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))]) + case .paymentSavedCredentialsCard(let id, let title): + return ("paymentSavedCredentialsCard", [("id", String(describing: id)), ("title", String(describing: title))]) } } - 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 - - 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() + public static func parse_paymentSavedCredentialsCard(_ reader: BufferReader) -> PaymentSavedCredentials? { + var _1: String? + _1 = parseString(reader) 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.PaymentSavedCredentials.paymentSavedCredentialsCard(id: _1!, title: _2!) } else { return nil @@ -921,47 +421,29 @@ 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 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 .recentMeUrlChat(let url, let chatId): + case .peerChannel(let channelId): if boxed { - buffer.appendInt32(-1294306862) + buffer.appendInt32(-1566230754) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + break + case .peerChat(let chatId): + if boxed { + buffer.appendInt32(918946202) } - serializeString(url, buffer: buffer, boxed: false) 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 } @@ -969,85 +451,871 @@ 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 + } + } + + } +} +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!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api16.swift b/submodules/TelegramApi/Sources/Api16.swift index 916951a39e..830291d176 100644 --- a/submodules/TelegramApi/Sources/Api16.swift +++ b/submodules/TelegramApi/Sources/Api16.swift @@ -1,721 +1,126 @@ 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 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 .replyInlineMarkup(let rows): + case .photoCachedSize(let type, let w, let h, let bytes): if boxed { - buffer.appendInt32(1218642516) + buffer.appendInt32(35527382) } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rows.count)) - for item in rows { - 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 { - 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 - } - } - - 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) - 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 .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 +128,802 @@ 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 + } + } + + } +} +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!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api17.swift b/submodules/TelegramApi/Sources/Api17.swift index bf6fb0bbfc..31892c8e6f 100644 --- a/submodules/TelegramApi/Sources/Api17.swift +++ b/submodules/TelegramApi/Sources/Api17.swift @@ -1,278 +1,331 @@ public extension Api { - enum SearchResultsCalendarPeriod: TypeConstructorDescription { - case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32) + 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 .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count): + case .recentMeUrlChat(let url, let chatId): if boxed { - buffer.appendInt32(-911191137) + buffer.appendInt32(-1294306862) } - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(minMsgId, buffer: buffer, boxed: false) - serializeInt32(maxMsgId, buffer: buffer, boxed: false) - serializeInt32(count, 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 .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 .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_searchResultsCalendarPeriod(_ reader: BufferReader) -> SearchResultsCalendarPeriod? { - 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 _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!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureCredentialsEncrypted: TypeConstructorDescription { - case secureCredentialsEncrypted(data: Buffer, hash: Buffer, secret: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureCredentialsEncrypted(let data, let hash, let secret): - if boxed { - buffer.appendInt32(871426631) - } - 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 .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_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 - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureCredentialsEncrypted.secureCredentialsEncrypted(data: _1!, hash: _2!, secret: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureData: TypeConstructorDescription { - case secureData(data: Buffer, dataHash: Buffer, secret: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureData(let data, let dataHash, let secret): - if boxed { - buffer.appendInt32(-1964327229) - } - 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 .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_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 +334,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 +820,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 737828ce5d..ca0fd02867 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -1,1045 +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?, premiumGifts: [Api.PremiumGiftOption]?) - - 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, let premiumGifts): - if boxed { - buffer.appendInt32(-994968513) - } - 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 - } - } - - 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 + _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 - } } - 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(-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 @@ -1049,289 +85,1983 @@ 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 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 .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 .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_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 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 .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))]) + } + } + + 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 @@ -1340,50 +2070,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? @@ -1391,7 +3190,298 @@ 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_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..9dadf48c72 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,1209 @@ 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?, 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) + } + 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 1f202e0395..58fa0773fb 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -1,7510 +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 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 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(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() -> (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..1f202e0395 --- /dev/null +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -0,0 +1,7510 @@ +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 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() -> (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 { + 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/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 62718b4098..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) @@ -456,16 +636,18 @@ public extension Api { } public extension Api { enum InputStorePaymentPurpose: TypeConstructorDescription { - case inputStorePaymentGiftPremium(userId: Api.InputUser) + 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): + case .inputStorePaymentGiftPremium(let userId, let currency, let amount): if boxed { - buffer.appendInt32(1147243133) + 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 { @@ -478,8 +660,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .inputStorePaymentGiftPremium(let userId): - return ("inputStorePaymentGiftPremium", [("userId", String(describing: userId))]) + 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))]) } @@ -490,9 +672,15 @@ public extension Api { 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 - if _c1 { - return Api.InputStorePaymentPurpose.inputStorePaymentGiftPremium(userId: _1!) + 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 @@ -818,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/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift index a15122379f..57ceaa6cee 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: + return nil } } } diff --git a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index cd37a30e9d..b6412810b3 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -3502,7 +3502,7 @@ 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 { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index 3ac874fe5d..02d4e6ac9c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -29,7 +29,7 @@ func _internal_sendAppStoreReceipt(account: Account, receipt: Data, purpose: App purposeSignal = account.postbox.loadedPeerWithId(peerId) |> mapToSignal { peer -> Signal in if let inputUser = apiInputUser(peer) { - return .single(.inputStorePaymentGiftPremium(userId: inputUser)) + return .single(.inputStorePaymentGiftPremium(userId: inputUser, currency: "", amount: 0)) } else { return .complete() } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index 043ec2659c..9d9e8be625 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -541,7 +541,7 @@ 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 { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift index 36f1f53365..2ffeadd0c1 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/ImportStickers.swift @@ -170,7 +170,7 @@ 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 { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift index 0aad8c5696..c1321e692c 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift @@ -49,7 +49,7 @@ 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 { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift index 556bd90a04..ec51d20bd3 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) @@ -57,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) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift index 10dc4e700a..57f9fbc734 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift @@ -66,7 +66,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) } From 794d415e7df01f47e54015d18fe3c1d99c4218b8 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 12:11:08 +0200 Subject: [PATCH 048/113] Fix flipped static emoji --- .../LottieAnimationCache/Sources/LottieAnimationCache.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift index 85ef713466..9cac2ad1a3 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift +++ b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift @@ -33,7 +33,7 @@ public func cacheStillSticker(path: String, width: Int, height: Int, writer: Ani 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.withContext { c in + context.withFlippedContext { c in UIGraphicsPushContext(c) c.draw(image.cgImage!, in: CGRect(origin: CGPoint(), size: context.size)) UIGraphicsPopContext() From 9a115af042f7e709d90d66f5a9a2c03de629ebf0 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 13 Jul 2022 12:15:10 +0200 Subject: [PATCH 049/113] Various improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 15 + .../ChatPresentationInterfaceState.swift | 120 +- .../Sources/ContextActionsContainerNode.swift | 4 + .../ContextUI/Sources/ContextController.swift | 1 + submodules/InAppPurchaseManager/BUILD | 1 + .../Sources/InAppPurchaseManager.swift | 36 +- submodules/PremiumUI/Resources/emoji.scn | Bin 0 -> 27377 bytes submodules/PremiumUI/Resources/smilie.png | Bin 0 -> 4044 bytes submodules/PremiumUI/Resources/sunglasses.png | Bin 0 -> 4016 bytes submodules/PremiumUI/Resources/thumbsup.png | Bin 0 -> 2877 bytes .../PremiumUI/Sources/BadgeStarsView.swift | 54 + .../Sources/PhoneDemoComponent.swift | 8 + .../PremiumUI/Sources/PremiumDemoScreen.swift | 22 +- .../Sources/PremiumIntroScreen.swift | 18 +- .../PrivacyAndSecurityController.swift | 86 +- .../SelectivePrivacySettingsController.swift | 16 +- .../Search/SettingsSearchableItems.swift | 2 + submodules/TelegramApi/Sources/Api0.swift | 5 +- submodules/TelegramApi/Sources/Api10.swift | 1436 +-- submodules/TelegramApi/Sources/Api11.swift | 1784 ++-- submodules/TelegramApi/Sources/Api12.swift | 1520 +-- submodules/TelegramApi/Sources/Api13.swift | 1576 ++- submodules/TelegramApi/Sources/Api14.swift | 2238 ++--- submodules/TelegramApi/Sources/Api15.swift | 2116 ++-- submodules/TelegramApi/Sources/Api16.swift | 1530 +-- submodules/TelegramApi/Sources/Api17.swift | 1696 ++-- submodules/TelegramApi/Sources/Api18.swift | 1684 ++-- submodules/TelegramApi/Sources/Api19.swift | 3932 ++------ submodules/TelegramApi/Sources/Api20.swift | 4572 ++++++--- submodules/TelegramApi/Sources/Api21.swift | 2292 +++-- submodules/TelegramApi/Sources/Api22.swift | 2160 ++-- submodules/TelegramApi/Sources/Api23.swift | 2156 ++-- submodules/TelegramApi/Sources/Api24.swift | 2342 +++-- submodules/TelegramApi/Sources/Api25.swift | 2380 ++--- submodules/TelegramApi/Sources/Api26.swift | 2396 +++-- submodules/TelegramApi/Sources/Api27.swift | 8658 +++-------------- submodules/TelegramApi/Sources/Api28.swift | 7510 ++++++++++++++ submodules/TelegramApi/Sources/Api8.swift | 178 +- submodules/TelegramApi/Sources/Api9.swift | 590 +- .../Sources/ApiUtils/TelegramMediaFile.swift | 2 + .../Sources/Settings/PrivacySettings.swift | 7 +- .../SynchronizeSavedStickersOperation.swift | 2 +- .../SyncCore/SyncCore_CachedUserData.swift | 43 +- .../SyncCore/SyncCore_Namespaces.swift | 1 + .../SyncCore/SyncCore_TelegramMediaFile.swift | 15 + .../TelegramEngine/Payments/AppStore.swift | 6 +- .../Peers/UpdateCachedPeerData.swift | 7 +- .../UpdatedAccountPrivacySettings.swift | 18 +- .../Stickers/CachedStickerPack.swift | 26 + .../Stickers/LoadedStickerPack.swift | 2 + .../Stickers/StickerSetInstallation.swift | 3 + .../TelegramUI/Sources/ChatController.swift | 29 +- .../WebUI/Sources/WebAppController.swift | 17 +- 53 files changed, 27836 insertions(+), 27476 deletions(-) create mode 100644 submodules/PremiumUI/Resources/emoji.scn create mode 100644 submodules/PremiumUI/Resources/smilie.png create mode 100644 submodules/PremiumUI/Resources/sunglasses.png create mode 100644 submodules/PremiumUI/Resources/thumbsup.png create mode 100644 submodules/TelegramApi/Sources/Api28.swift diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 39090862be..e79ebe07fa 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7843,3 +7843,18 @@ Sorry for the inconvenience."; "WebApp.CloseConfirmation" = "Changes that you made may not be saved."; "WebApp.CloseAnyway" = "Close Anyway"; + +"Privacy.VoiceMessages" = "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 %@ emoji."; +"ChatContextMenu.EmojiSet_1" = "This message contains emoji from %@ pack."; +"ChatContextMenu.EmojiSet_many" = "This message contains emoji from %@ packs."; 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/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index b4b0647024..f338feed55 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -372,6 +372,10 @@ 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(packs): + self.text = packs.count == 1 ? self.presentationData.strings.ChatContextMenu_EmojiSetSingle("name").string : self.presentationData.strings.ChatContextMenu_EmojiSet(Int32(packs.count)) + self.targetSelectionIndex = nil + icon = UIImage(bundleImageName: "Chat/Context Menu/ReportCopyright") } self.iconNode = ASImageNode() diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index a2485302b2..80c3cdeabd 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -2226,6 +2226,7 @@ public final class ContextController: ViewController, StandalonePresentableContr case textSelection case messageViewsPrivacy case messageCopyProtection(isChannel: Bool) + case animatedEmoji(packs: [StickerPackItem]) } public final class ActionsHeight { 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 0584b2267c..1e64af4ddc 100644 --- a/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift +++ b/submodules/InAppPurchaseManager/Sources/InAppPurchaseManager.swift @@ -4,6 +4,7 @@ import SwiftSignalKit import StoreKit import Postbox import TelegramCore +import TelegramStringFormatting private let productIdentifiers = [ "org.telegram.telegramPremium.monthly", @@ -54,6 +55,15 @@ public final class InAppPurchaseManager: NSObject { 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 @@ -317,18 +327,32 @@ extension InAppPurchaseManager: SKPaymentTransactionObserver { Logger.shared.log("InAppPurchaseManager", "Account \(accountPeerId), sending receipt for transactions [\(transactionIds)]") let transaction = transactionsToAssign.first - - - let purpose: AppStoreTransactionPurpose + let purposeSignal: Signal if let productIdentifier = transaction?.payment.productIdentifier, let targetPeerId = paymentContexts[productIdentifier]?.targetPeerId { - purpose = .gift(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 { - purpose = .subscription + purposeSignal = .single(.subscription) } let receiptData = getReceiptData() ?? Data() self.disposableSet.set( - self.engine.payments.sendAppStoreReceipt(receipt: receiptData, purpose: purpose).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 { diff --git a/submodules/PremiumUI/Resources/emoji.scn b/submodules/PremiumUI/Resources/emoji.scn new file mode 100644 index 0000000000000000000000000000000000000000..adca0e2664b6bc1b882f4bd921b9094b094d929b GIT binary patch literal 27377 zcmeIacU)7~`v83I3IT$IA&L_j0TMC*_W&e2peUQL3?V=?B$xydZS8GqZMC*q_o@S} zyK1%0I_hZM+Pb@}qpoUOZMDONJJqH@W)&83YDNrRDi0`a8!q0LZ6|} z(HV3eeTlw7x6w~nCN>1i#q?M)R)X2FQP^A9+t@U0CN>vaf;C}FvDMf{Yz4Ln`w;cS zE?{3^Ut(WjUt`~37qM@#OW0-X3U(Fy4!ee3M{#H~b_4qZ`xE;Mdx-swJ;EO22*+?7 z_rv}1K)f3siAUklcnmJUWAQjV9v9*wv>#8v#kd6TiTA}b@j>`tB*wGw9J~P6;}!S> zd@cSyz7AiHZ@@pmH{zS{5An_T7JMtd2j7pM#lOKXUq~sIRGSsK*?{ z!8kaF;E)`O!{PXFxEx=OAIG1=;{+fHia~{(Ku#nliWAL=;RrafoH$NAN5~Oz5;$Ux zjMJ0Ti_r;iv=Zh&rLps0-?fB2YIJ ziK0+6G%rB0FmN$Qh(ss>iQy|jQY1r(CkLr5vYa3NuZ0E~Mw@HvYZWjD3|6D5q^_pX zVKzDnY<3IO39hnLD@<00+1aQZU1zhJtj=B#xFF7*`#hyqs(@jwH81ta@gwaMpIsPW)ZxN-O03G233^SN_VF;NuP`yh!EmN zD#jp0<58)1;f~3m57G}ZU1>U%xkkBe5aMI}H2Pjt+TiA=C+MHgp&l@xJy9>z8}&hb zQ9sll`JxmQSLlRJbDXBSJV%|$RGH^6nyjXRYP(?+;1KQ%7E@H}J3;J+CZf{XH@Ato zyWYcOoI+`6AWBDay$g$0c-ul(k{RznU^zp)2C4}ukn*3|g@bdlSXT875TY7s08%Z| zp$wD>un$6mQ5G5k1ec9+P%g?t`M{eBQ4ve)#VEVX4g+Meo2}JZcDMrdISmY171r5+ z9v}f@YP6UE?=7TQY&1B4G-?c$wuS;5kR!Y_z-5Gis(`7f*HfDEjZCHC5uZ!@o<^mp z3|_Dt8IZAHaE@ezsnMZ_Yctzkf`-wYC8&b-p}FP!PB|G$h0R#c&`);r{2FAik1*MR zr~A6bp&Hec^Fs#b461h;Dl8_2nVnt+d*f16jm$_{GB~Ft?-bkl2xMD|ET|S)X+JuM zo|BNf@{RCk zHx!%dEx-V*)fSV3%OZ+qsfIzuSAmC9X`Y*y(wMBwzaPJp`VfB1l}qz!|4b<5sllb& ze9P~NX!J6A1-**Kqu0;`^g4P2O+=H>n`kn63%!k|psDB`G!0EhGXUb5Xcn4{=AgM~ z9=y$bv;e(}7NSLHFW#~P$9IZer(JHhWtwC$i`)D0nk2atW&_=WgeTX*0 zcMCAQt!NwC4(x3Q`iOn&U1&G^Y!CVv-h3ZW=Vr*?&;E~M|36`$?}sP*;mN1yAUXus z!*Caaj>5BJ?DOOBe*&E>=L<~0xg7O&)4)nYor{DO%m7<~vU8X@sxlazHhVc=^3Q@A zV2d`GytUZ|YqcrU)-c3wt7snkjVO4l;1XJH&-1L*R`3^p+%-2wI(jw~-)25M{uvYg+J9UtXCreSU) zON1e{HU?;hxI8E=Ho&gHP;FA%4X}WCZ(W|8O`a++qAYQEu#i({HyL0P6Ikood)d3m(AMBgL z_vMFkqtdj@L#cIXaAj)u9(pHoAk%&t-ojb32O>nJLr_kvl*c-^%WughT5lYu`bQakb(}Aus z7tj~5Dh{**W}DCjrUbLs_zHbp05zG_xCw5Qt(U8duwZ@LykvQA94@0P=qmaST|?Jd z=Iz=%z;ab=vok!8rLwX**o&Es7E?~6!)dB@tyt{)c>d_OGw02nyXV}__fyWdo16NN z#h*^iTnLNTZ1^!706G|!F<7@;FLwvomY^T#5N3@{M|aUZ^fUSe-A515ujn`QJNg6t ziT*+l(ckD1dW<0q!*GniNQ}Zbm=DIqd@(=FALC&GSQ{)5<6}WsFcyM^Vr{W7tR2=K z3&%QO9Z?w83G0k?!Mb7*ST`&Zi^8I@7)*f0VsThJCd5Qo0w%^Jm=u#?iLf@suv_>z zNQtpzSjWYX!`?CZSPv$jP4#5TV!g3GSYNpI#|FUD6f6}>!+N?(KrIP25NgL@3N{B0 z3785~v*~PDL&fZ|AqLa2IR)&$q|}XcZ7ocrvI;ZIO%J<(DQT#x0@h)wOmA%7NUF>x zOC>O%aCb%Ej4YGMH`vY1+#=GF4SSGat>*xFo)90?9gD+ z2e~VF_(QP+)>>fpF76)8Vk8?jre2_TZPh#bVo#Ltz>yB;5uVyqdMr1-}Ong&7#H z6*>hm25`|5z`hgK0oa4r!Lk>`-a?yRIQF!gZ?f2!9eRP;k;yFYo{8#uxpID6Hv~E6 zF)i=vAuSfp67MpeM=TOb3`U~~cB(A(6nPL1G}a2w-gM*v!8OjXu(+G|jH3s&UKn!I zYAM?Z^D?ewkXb8X>)>pZGb=RU2qZeNAXu0^2q48nEg=nd*lsv-ZS0ztUJsK47PYqK zO4#i;Q?XaK9^3;0>MaJl8;`~8kyyvU?EB$frkKF9(g#4n|?jb!Vpx!4$f+_Fl(|)s^FnDrYld$JlO8lIZC_-0#M_H0ZR*A zmh;=UdT#)!z7}Q%2oC5luGi@imehZ&FmT*Y>*QLGxOBMJ>5|?Pm3nyY+{N&W8ly<`-r$^Ubvl~`J7ZRw1R@|P0h>o#Ejy*z%x2L}7C%@f>BD?_ z%49uzL?klbEPhaPW)E49q~1&x$WLgTrcSpH59-jdQ|{m#tpa+|%H@0?nxM(7Af5&x zo+i_5wc&8+uZ5WkU_=xa=_7njfK1jG`sKRAy6S1L=r|wkB79S!CA-T--UE&#Rw*ilT6wU079A( z;DlDY(g|!CS2~SJSJql9p$r3aU1e=0lRg0HH%8T)AWbkNGhvk3)Bx!-kd6j|HADJ$ zNQc&%3=V`y9+U4h8EYUdgEY^cn=OZQf1o8^wO6{rEA2Fm1~?It+v*zG16M?xF+L)( zPoLfq8dHM>&OzcKFp~}T$_Qro4c114T<^@(Lct7fBLK-g6Z`b+DNd3A`aPegKJ=7& zdV(2SSBYPSvSWsY9c#&JsoRogYeJ~^1HjGHmb{9&2yJ~0q4r<4#;)i314Dm-q$wGL7dB!c%Hy>n?2o-d_;i7v;!*lk()gL|uZgGdX zI)cfTXXi#3>+PeMG|UO+k3xPRcn<|Zdl!)4#=&kl38b|B;En;=S>Kcm|$}m*UmCNGnB$wyQG)rk^OeL-VVNL5n}pevb0EvGh9pHOG1 zYt*lx3kd^lM=y?sQ^Xn08Oxc>d6%=E^D*ah&Q;C>A0MA^ACb=hpDZ7PkJD#@&s?9i zK6`vl`CRk)o$Jr-%1z>`xO%RY`wDj!cQto6_Z0UA_b*?*Z;WqW-z?us-$vglzRP@f z_@4B==KGglkYB9d0KZ(n;eIds&GB33_le)ve!uwp`$zis@gM4M_NV>l_;2t(4RERvp81ib!vXD=-sx#ZM(P4Z#%l}{I*M zZ|ys_Pit>#KdJrt_GjDw86FX?3?C8xPWaaFZ#s}2gdK)dXqe%T4{B6yZosM;S(78)zb?3Uyb35Ex~J>+5p5#|Mpz=|L>!2?+pSYKO}F}POS+xt_E%(VWM1Sek?SMBiSmo;9aR-I zBWhpN-RQ2-gQ8!EUK9OgjBiZun3|Z`F$ZIQ6T}J%1g{IW3U0=>kJZMGiCq)>bzDGP zYTU@UrnoclocP}HBjVqU|4fJrdkAZU^MxlxxTvSdEP7Y;c>tQvOfn|TPdbwv zkgQ66DS2D+z3!s!rtS;7U+59iV^ELRd+h7+ch6ou?LF7^ywxkZ*RWm-dY$hb+IvXv z$-NKtq57ovd8yCNK7aJ>+1J^3W8a_piTjP{x4PfW{;~Z{{g?H>Iv{d@VZf3Bmr^29 zhNUb{xs=*1)sWhhdL=C?tuk$S+Kqwn1BVY>JMhPJS-L%abNX-czVa94A1erjS}{p+ zLK&>gQ_fRfR7I+)Rclmt)jiZ>)gNmpO@`(j&3SEStx>y5dso*>_oD7V1}`HgV_wFU zOkt)ybH^ZjkZ#cQL0=D!8EhTAH49~Fv!-W#GbDD%$RQsMht#H2j-XLugd?eKv6KQ;8LNq@WsNTMIDOFMcec~`h5Lz z{exm<@yz0DB|S*+KL4g zca3u6Y~$_9w8|Nkw@d>}(@Zz222@R}x>-G-dV2M(n$((EHFwN%^E~st;hN!#hW|Dq zYs88Xk1Yk3^|jpEVYS<>!PXJh1GX-<(YDX)M0FGDE{*Iva^}dp_6+-S2j(bsY;%Uf zX6jgdT>WeHmq(?Hnm_9IhWv(2qk~3UM;~hxHco83F-A4!y|Lt2Jf0qZ^)>ZtYbLar zV4raQ^?t7}dV_q!{Kkoi$rI;Jd^D+Y(vdf1Z_ax2;bi0FBX1?XHRr9zZ&$s2VoJ{` z3#W3XTBn|SC-t3`(}JdrnRa#hpy^v?M9i2p;2xU%-Q+xdCmc-|+nh!#+5-F=OMtO}#g*`!MFi1)D=QPuhZQY20#mYt7b6+lsb* zzFoI{-;RDeHh(1fXvNNMJLm6eyKBmBzun_^Ki)HD&x4QaKEAWJdhgYJ<@>(cU%3Cw zfuRRZe3J3Wp-)wx?msy2;GRPR4(&YL_we>3y^m}?+Vkj^V?B;-KHlT_<`X?nY&qHM z0;Bj@!zh$)brA=%Zkg#uH;<#>Z?T4B640TbEY+i7Xap$f z#=*8>F(|oq!WQ8am~xy0LyjxxCi))TK|coc4M+{p1>^(_3or)M1vCbX3z)#{Phj`r z-qysq?%n?Z6IoF#HWbS)ZBaHFoQ9>4m4lS|pk{=-X8k6XhZP{>5-gu?w*)Js+tb|K zI)k%D@2CYes!393tp*V;R*IEj<**|$U=^4VtHexL6&yONu^P;b4M%a<2+;Y8v0BUu zQbfEk?B_w06l4bN{OGJI*y7tkfyrupLK%gJLuI$sddabhD{b{4ILrZC5Ri+8!+=z2 zEzCjF$_j-%YDs9)Ef-_NLYBcG)&)Fz_sZlK8o|PaNfd*&eu&9F1Z0?i+;$*J9N}nI z&J>s#VRKa#D1|_PU>IdHS30slp_ADxcjE{8`f}+`bZ5B0xPacl{evv#{Cu&`7#%^ioLAakZc}*=kKr zd!u_g&BNZs7B^w@u?2KDIYc0>w1`bI@8C)?n${wNTl_|s)6wqU)?n+9u?bs?y-&x`f+lP|wtfqjJS#CBo3u|3$waIn~i?Z*yapV0BN zkQUJiw3wFAQd&kQ(n)kO-JR}1_oRE#y_qHsVu#=yas)dHzvJ*df_(Wej4QLn{dAfl$V+yvLz*xk@h`brQ zAcpV@E1PAsMHQxMvy~}a;@0CbbBGZ)Lcdw{PIt#{wB7`GHoIt7$WY4kukeFb(8j%vSP_pt|noFlZHR?td1pDqAYKHn*RyQM^T|W36K2}-{Hddgm z%3;mF_*_1j#gA~meClVeRO-#<>s{B?{ZdjqsTDqw@$PgXUDWc{z3|?x(a;Z*^m)X z*20F~ggY-bQ^8z8pw;CB6z@Oxu`W5sx8WbPnjkyzU348ivV|x<#`m_KAP4Yc&zc}G&J3UE%1)4Q7*&Q(w(j~0{{6GM2IkblqQZeWwXi7Y8W56l=Ui!O*OE6<3xUnn zx3F3_LLT71w}R>q{7<@p9^C@f-}s|eP!Sm6`z)xQj*u+AEM=I@Hzn$ms+5qhwkaLn z@EP!Gmu&-1_kKKJUTpsXYj4MMq~%#|6$W@w2}qMbLiM0+Bf9!tOAftKh* zbZ!l81QGWvXj`%Q@K$V|#i7hiMybaFE=Ryk>iOQRzAW{tq3XrV{iUF^kC|(0ZcHQ- zJzGKBi|9?iMAI$M_9ObYhBlQ@KMUGt;r2gH0Y2`=Vh)kt3a$d8kRDIJ)&f^CQPLW& za-#ZKa6O$8-Cd6)fakU>*hD=sihiAbqowOcVod9ew-?Z(I_De)a*nhQ>LRYPWCW)ovQ%ia;Qi8-(z@>=6u#zIZRTxMPS z=L3(SfTP@Es&an&gmrC;v67c{E%7d~kXS@4CYHc4jIpnk5X;~S=1Tvj52in5Y?4xI z-g!U8_uiaT(ABkAAJbF80EyAwF&~=wb6X=3E5RCxSVh0{{~K#0VlA9gysVLkbx&F& z5gVA34D$t>BPdI3BsLKr!gUL=6^V&$#CBqbw>1*+5wz!JjYNF>G;1W{0FuztS^YcM z95XlsZ2gP=olDPfV-!mKU)Ao@yy`%$*{#*?T&{0aS_;!6V^hy++lhnEmF&-z?9Y|# zu1UfCdz7%~xsv^<+W8igc^gaom)i3GvYHnRO!B#s{kf9;xsv_4lKr`o{kf9;xsv_4 zlKr`o{h3O3w_N2gakRDm9ApU3(w7q_K~?*&`f}nlJrh*M-g;u4f6iE?wUUkp#Jif_Y*&ZynkMcXz2k7%A)_B z+L842miLqVf5`jix03fS`&W5C8BTTs@zzt7c4Q>>GZ{_BkOD@)OfLW_{k!yHdI>9F z2H`{66Wi#gs?!)%+moMW43Y_?)LS@5%E&}|A-%|hL9#p9qm^)u>`kUUOE}j`y7~_# z+W%d*MP`tLTS1pa4xyXqr7h6qkh!g)DFY+|Ah!iD-hvwcgZ@^ z(V7U!dLY6TEkKSYC;m@~aB?dmoc<3YT-k~UKlyheTtI>X|9_`+BG;1}$PdVk{Q>-0K$eM{H3NKoE*cl`tT;8|TiU53tRbN+bw&D1E(*#Dr-p%6uQLq(AkMQ@}xd7z@W z6ew@JprUwG=(C`DIzkv3`k;zUDIL0;OA$nlNQvsXf|Z?b`}5X-ndf-}RuzfUokCt>ra9q>bD> z#tFw>R%@tZd~xM91}k_XvX62~AyxpGV>oQ!En3%@%lJWoDOYn?4;rHn(Z?fSdg<|F z-?P*v>O*jn*aGjimD&dHu$|iRUwPC0n;V@hiy!i&8(oA9(TC|{r>ULPF6eYOwTJq+ zwKLrj`sj0Ky64Vx=(#f;yBa-rrhD#8_uQH8xij5!XS(OkbkCjXo;%Y$cc%M)=}d

N0hOx=MWqZt~Zu8`Mqe7WF-Ko4P~&K%b`1&}Zp$^m+OM{RRCc z4IYy8H}pmNTlx}xnW_F0b=Unx71Uk#kNS(rrLWLeJzpP4xqsiWx$pwPZlAoIMyqj% z&0=PJ!a^Y^V!fr3$@2IVFg|-N*{+vzd$|>lFq!HcS}Rk*Q=9Rtf#5ujK@eh*2{zld zrMAWl!JL>V*Gzt}D<8amz-h;sYb(mDdonW*B7{N7F0PV8pjDF{Tz5cB0M2KYTpM`4 z*s5E@?ZG$H^Lm|TZ!NatW`NX;(+Bv4x#ICT$^dBaJhVg1U01JsH+*%CS|)56G}xTQ zye{i-=HRjpeH=crfs%t0gdOLEz^^R?JZJ~ka83tKN4R$8bm4Tx4${}b`RNAyZqm2t z@8NozzC-^2*B|Mh=)2$^6&SVWr$yO|;qVcax_>?dhhY-C8%MYj-$lKe#^&6dE?CSY z_H289bA&7BqGlMIbM^X~#ca;9gBR17L|Wu)YlpEpzr6fG1SFcR7&%g~V&wny|3Rdn zrT)ASSD2vFt}sFW5*4U90FX)+0be$}&nbu{)b8ILZ#_IAti8w0mK)R|IzFkFHgjlB zL22dihHwr=a46D92PbFcj9m2G07!;Nq;hc>_A3=W-FGACzC+E z)RW923&}FF5~8Eq$+6^%JQ*Xe{(v)1Q2lgbL5;M5CLQu zr-D<-sp8adR&dsGHgWbqB#_gbvz#lOpE!3pKXdN;U_Q7H>GLg@%k9Heb91>baHn#c zxM#S(LfnsN-+sO--#lNv?`ys@eAoHz^4;%y3?hI0=GVrrouAlG?w9Fj_It~3vEO=# z{c*3j&3lnIj`uomBJWM!RNge+Y~Ea66K^SRE$;)~7T!k?FXSNaGv1fHZ+SO) zw|KXC_jwNkumHb+;DB}k`2iIHBLnOKuLZmwFe6|^z=r`_0=5Qh57-f~GvJeeLjgwu zj# z|0Mrw{@oxV$UmqPjArC@+4fPET4uxo5p^>4Y z(1g$)p(&wih((egS{Passt+v*Ee)*-wT0G&jtm_WIyQ8C=v$#vA}2@Aj9ePII`V_a z-I04E_eXvjc_{Ko0=EazCF)zi?F>_*;#JnG~F=jW!6ge03P0aO}A7btckRU)1EC>~Z2|5Zo3%Uxr zL9~$s!9YQ#AYU*{FkD~}SOsGRwBQxNc)>)$n}W9lQv@>w3k7QgCj_4fP6^Hk&Iv9E zz7%{dxG1`xnj_n%TEjB7PCN?%UK2{Vf zj+MqH#wN$6#^%PB$5zJH#=a2ydhCqYMX~E*_s1TKJr{d5_CXvT7Zeu~*EX(QTzFi^ zxXy81<0NsixTLu5aXsUD$MuctAD0rRiz|sU#W~`}#JwH2IPPlP&A10~f5ttGdlXN^ zQ}I6WzVX5FUE?F-yTwPv%i>ex2gb|emGSC$ZG1-jp!kybviM=~74envRq-|P!{aUS zW8?}^_Vzd!!-_|x%c<9`=YLO&r-*hUy4Y%6Rh3>ON7vBEf^P}obT z5^97xVWx1faELHlm@702O~PuSSvW#iE3^qm3LV0FVS{k8aISD3#AkU|xLo+D@Tl;% z2tlM4QWPW#6SWt05Oo!G6Ge$)L`kANQGuvPR4ghLm5U4_qsSzxhIlR`M71KDXr#y? zsu#@>%@ZvUEfg&lHHnsqmWx)3R*Tk()`>QVHi|wJZ4qq~?GPOl-4XpLx-0rwbYJwV z=y%bdqKBeK2`B+iAQLzV+yuV_UP7CMIJPoP@lDf&^Q_n1l%la}(Ak>`ge9@MXfCgh%3Vu|O;mi^WoLcX3Z~Z*gC-TC5Rk z#Tnv4akbbi9wDw3+r%Tq4spGBym*564e=!LWbxbLsp4tk8R8}4<>Hm%)#CNy55$|q zo5lOY`^5*upNdb5uZX`BUl-pLe=oix{!x5a{8)lX2ni+ek@!mdB>|E^iBQr@(qEDy zNs}lgYKc~oAt{s;N%WEuiCHpQGDh-(WSoSC7&qf36C^Vwvn6vS^Cj;}7D<*!mP+1} zT##Iod@s2p`BCzVNM+I_X?Lkys+6jwT4{!K zkTgp=RGK55Ae}CqBb_H*AYCF|Dt%A7Li(X}vviAeoAeXu8Rghh-juy1n<9HhHeEJTHd{7Vwp_MG_P%Vr>_gcW**4h@*+JPM*^*$=XxWcOsh$Q~q;iJU}kqF*8}u}vZ$;`)RpN)sy*ZHaY>BNH8oFC@O4 zI4N;q;?l&eiJvA>Nt~qcq>f2(Nj;K!CG}3~o1{+CBAs`BnKf`3?Ck`EB_R@}K1QYSmiRI@Jc%M%9O^Evjv* z9jcwG-KvjO`&0*1pQ;Y2j;M~QZm907{!sm;`df{wNi|2!Rku}#soSZ;)dGmq)Jxq* z-A_G0ovI$FmaDVXx$1m%p<1slQJ1NQsVmerwNpJxJzD*u`X%+t>Q~iM)$gdMsb{E{ zs5huLsy|e3QEyZ4Q14XlRv%ZNRDZ5Mtv;(hul_>)mHHd??+^jXPs7u+(S&H)YT9YS zH3ChnCQc*N^wOv_8jVhqsTr&pqRH0eYK$6_rdngxjL_6-Y?_f8hi18ElV+P{hi0c{ zuV%mI6U{-*8O>SEIn4#lHO+m^ubSUAe`+3T9%+#l*9K`rv~9KRwBg#05N)cfwwpFr zYtU9{YqZ0)Htk5QLtC$XMf<9Dymo?iy0%HXOuJmWQoCBaR=ZBSLAyu0SG!;PiT0rO zu=c3-xb~#>d+l%9huTLvq@#2`I$xc?uDvc?*Fo1w7q9EB>#OUpOVOq2(sc@*N|&cA z&=u*5b)~v;ok3^RnRIqtgRW6GR!8ez(T&$l&`sCP(9P7%)-BU*(rwml)os^(q}!$2 zquZ%*MHxjoMTJF%qK2Xuil!AEEIM3twCH%ziK5d*mx`_x-6*$&VfqSvrM^mEqaUuf=&kxXy&(+V@zpG!Q zU!q^Ce^0+cze>MG|Gs{`{sa9c{bv0U{bl{bVs3HQ;$Fp>#fIWnisu$@C_YqtzWDp% zzl$H0_>>4s5=tZ`vXZ2d?j=1-dYAMq>0gpkl2(#lq9{?7Xi9V?nI(B8WhK=mbtR1@ zuavx5GNa_(lI11qOSYBlC|z5+y>xHs@zRr}pO>C4ODOA6)~_tBOk0-iIxgY3>&hA6 LIXRzIP)8Rj5#bTCNbtNj7Et^)EG&{Sl$XELPTPT$$|Z06C{`ht? zJ-u`F^y_1G`%~4mGqc;T-_HB>d#~T``}@6$R4PRqqZ@Dxa6E7va1_uN=;=6WfR5Gy zu-7_v0ZrD?2y6yE0M-Mmt@j^?^nZjxMH?`H;lOC%RO@vuYUChj0+s`7fd2qXt=DBs zIT}DO;0wUHz$w6}Xsg4Uz!G2%uo(3mWkb0bz#+idz!cz2pii{b$;lRA0Wb@g3w#!B zbqW)A1Nb~}32-scKjON0WfSl?@F=h>;=1G{t_E;6a5ZpV)DMuu^*Ho!{YGD28C2%`tM5{+|7;}_3JG%>s)=nDmH z0Dl7R5BM5wnFoLwL0%xJA)p3$3OFZ-!rLKpfeV4%rV9?j0D7Y(k0ZH;B!4vgJFR{%}A$}hNYk-9$jUNSl(R|C-s-a&4m_@R{6D21Av;7p{ z#{ll8eS7la!bIS%Qco^*4sbc}V5t{P2!zXlhrFItiUEv3&WeQiF%nqi3lob=>a@VDiUHv!L}=8026`J zjZ`He3cdoImG2J<4FRiArj3O1Wfgh+HTimgsU(fx78rr@Dr6;J50KpbZHJt_K&~EO z0!ibyB}Sn6Kr3krN*o{j$x;4ze1 z#i@d=LXpQ4fooAzQW*Rdg}yCD$s=t#0b|hjcn!fNtSpryk*Dz4gP){QDd+KUDqg&w zN~KOuW!5p*(JPfo%?!9ct5d1e$wk(uPb!sqGT{1@!ow*?J)J{9R}^y8J!GrQMFYwN zTJQ0^2M8vt`W+OE(d_ZOCs6jYxX_FebhJR`B=F0`r}056kzN}gl#jr)X7K>()|*Q> z_iGr80DFOtN1%hk!N6e;hRj zkg#!s&vKTdzzM(XMgohbLVs9*^~6U{xdv;c*X{v^5Rb+OrD6Bm_yCU>Ck^sd@v5u22dMeMV#!zO!p7)2?}EI!w$^N;5Sp+Q%z9Rf()PrjR|pJ8``7C6kB|r zUyr#RK=$G@mftYLftpG*8Hmf0<#x<;+cthTcxnXpo2ZCIi@~z|(hC?=MSN!e06Po( zz7{R?9FOj%+2o(?`yF!&ZTWHvFb%m`8-S;gkD%1@!e)3C@ygqqufc8ve&_n^>%gUG zwe6EE=lIQkvp3K0eobqU#W#@=e51g*aiL!&@iKs13Z>g=-S{?>fR|DDnwt(j>r;{A z^9RYTnz|6BZpnt*`x-UjeJ>dER=Zzx!LQ5B)^~q+Czd*?t@-ZHGIDq~f=~0tKav!QX`GHnc|IHxFVpde(Q3B694E zB|fW;aijr>VqZn_`1NGU+J24}m5g1l3WbB4;sr8&;oDJw#$4-tPo$oi0GtSXiT0g= zv=Mj(?YXo7DVg)h*j_e#{r5~8Kq38H6HsRzpcTj=$RI`{gE$WVLXNod0lK@Fqd0+8 zc+)KoFdJ;CRecKCR%Ip2cS5=0Z7g~3@Mq8 z$Z^fENFlxdhv<7;jT(Iwy0Hq0T-^*rnOVo8q13H%GHC#fz&blPbP?)){j!?YKK!v{ zkFI$c{gd-4JsPMt>M@Q%{`S6TlG)pOe+Wt=)7d&YISxo`{%rB+9(0H9K?>f_kd(Ux z-O*c6H@?|=|2}H)QWw*@AvxPb)a#u_rVjB+;4hB%vw-tUyq23+f$_Eh+yh)~pwJfd z=;ze-4?=fDzWwc%1542)@-12q6@I8fuH`OP9c%-rAkzR+q#J)X8lFDGtPj5{8rH_5 zd<-X&Kc~=}*5BKhig*UK`L(u6wGJ}|a2V>woWAd7(n+0iQEMI3(3igw^%`~7>$fRg z;=K<^#!Fwxl`es_0lb60P!mx? zW5^Uw+VU1Qw zkQpj}qQSD)U=6d*K!ukuV*uGElg$Rob<^EChUWPFZZw8Bp)YfX^?o;Uf$z6|c0j9^ zcA#txy3-D|%I}IMkhy|Hf?^(-H_m8-WglFua~i-rTI=ddVGO!cwmLrZ8>CqZ)z%TG zxCbvh<9a{dVA%(I7N;ca70leJ9mwpeAzoRs%7Oi4cK?GgH~Vi!Z4G1^z$d`-hAwik z>%FObJ?(}2kRQdyZvJ*u@7uA%kJ`G;uM{v(t~ zAxBZ*hIx@qds z^6nxe_*hJS7kagI&f$ix-)h5%T$@HM0M0OQ!41f=i=`tnh7%k=2Vm|C2$Su|QM4Sb zV6H%`Z~Huy@qOTrhU)VYaHjjiTm~?K+*vNXay@W|kMoZ}hAiyC|*@?rSNcxHO@jtOK*o|$jkxRrPh&(1~*(gvDd4C;sc<3}Rnu-(F4QIF9J zxm&xCJ$+0e_Mnxx7POkU4gC*WP-DMqz21t}IlSE2#c&JK0Gc4@wsH9kU<%HiCH(OS z%9s%*ozZfxtp%`M!W|t)CGr#OwT^wre_(3??AKwZck7FK5mVB*DM*CViZHj1orn@I zCluzN6xj3E10`=A3z~$O;&I}aBPWhrhPlRv0&Q5R2LS2#Oa&yoh}mV$w#EQ7w=mW9 zFQmZJTrv3pOelqH&H{d8u)Ma$9L!4M3$|S`2Cx>G;lC~i`3dUg5;A!lGf!PMcj8*~ z$wo0l0B9EdE@or>&Ig_|SYA1ED_R~mMFVmn7gQ@3n<8c>g|lONWj5N0tG)A6%r-vA z5m%H{-Aj(3`Djl*lgvfi!?jm#M)?O#azA>EEQ(@>0GmoACiJqtUkq0Re>PlZ+_?iK z!!*fyq)aZlQN3mfJAk>!6esrr(*r0sj&w#T*5-?k@4%d`v`N(4_&C9W^&14Z!CDDEls8W+^9noddX; zPjD-Hj{!f!Y@A>ej6tbuzZ_8c^YO9muU`YG2Hqf#v%x2Oksx9^=63H2i^0GRNYWJ) zE0BSeob1!D0e}Px%LsPt{s^r`-cM%0NgNrD0&KoRu$fNYN6|vQbd@Fy03^hCo#6BR zv>utV8ZyW1)7Y z4FD7oG?&cG7GbjzjgfX3bOX}$HK8csooM1@|MOKygxQ(&wlzJGK@UX+eH_tlv9}a$ zjAbHl=O95C0O;x9X;k4jaR3QDcafPTy%N>AGcts@@jP%50qi~=lmXbx0KOaK1=;~K z2xi$B2;Kld;ZCN#i0uV;mN4UlVE~}{z)Z}=xVLpyAl1~HL0>4WJ%g43C!^G43HiAP zeOG}uK7`i;IGKX5$aLn0+_DRkfz!4Nt>>4%;4F$Ir`ong_bo8Bs+V~Jn58z}p zl8L)>3bhyJp>61wMOA^Q4Zvn9@|=x}xE^6qhwl1kBd$km48Z0hltrYi8bTe?20RsY zMQq|`05+46P&5erVHC_py2p8i{xEFfY5+E)fJ=~zwcMT>Hlk>sM+xbXt`y>K05)Av z5Xlr2U)U$w>f~e#3V@x3Qs281KE;l5F#spM(3bA!T0f)oI)Y~KOHg3v63R@vR*nYX zW*8D?j6kLlNM-uun#_kR8ReP2yJpQp-b0KNe90S*NY1bP6S3XVFU);a(_ zvyL6W2J2W4tOQmAi-7m6-#5qfIbxxv3Jl;sGh#sa4S-IA@2D{FukfXTpA;L~KQ zQ<}6Jz(C*vU_5Ye!gUGCQs8mmQD9EOb#W!F1~3x15*VFyMGWzG;2vOF(iJHtZ3b{I za4j%6>54?eY~T;Tq@*iilNJLw3%DLl?pgw`026_ylCDV71~3S?1vn$gN+ihhz|YZg zG7)kKUAF^pEAR#_xAOspqc)g`+9Y<87y-rsw*x)nzHrJ}3j6>qA!8%X5ugsZ8{PM^ z&Tr1az|*LW+QxO!xJH0Mz@LGBaa^nlco+Bz`AN_!NK~4y206E}8 zwC2x9AB%y*fW3ZC2s#J2m#p*COfM9D?3*AXzz9+p)|}zU2o!Hv62At}4*8)oPhVxQ z3h0fJT|M!83-~Qr=T{QlQJ&j@f76`ldxf;kF!-|G#2Mu0$*ii}iIvhPY6z!|_P zMyisL1Ve$-z1~pj7BCMfZDdp~^YD0H<23?|BkTNXpfA!@aKvi_$iDs6gX<{ZHUbPI z>-=h>FPaZD!)*kZj*K9~EO{g}wHeroBxH61yO96B#(GZ)khEQ>b6-Xs{uX*nz783(N%kPa+3MrH z6M!3C{&zX>qryKFj{tSRGStY$i~^qZQGvM0q2S0NXw7>Z&h-z=9@N1vq9E8AsIAgQ z7u=IaK0;Z@pFblg9sx$;-gw85P6ODBl26|NZbL)iP~^lKhK9XzS%$*hrvd+=gj+Qw zcnM8(K~D;ww*OE(0z3>{=yLKBl<|`aQK0~Q6-|Cl!=L!n8)#U!JAGSpRf~kHP`sua zO>X6d2G9Ye9PQ_E@{PdF;p&$t{ZT^2FyL@B+O0zqwwI82)7+#gXMk2HV(So(_iRD} z9iKo`0~m$$?7Y~6l0W^*q1Gb}-y_iset)#A*@Koqn@|UQY`v~V_pdehc$RH|_Qa>= znL|TxH`IpR&`iDy&=Iv&8`L(Nkx?!}(sIjvUgHY;Zu@%ztySK#q zMxiLxA*j=XuoD@^CY1fM3^m4bGzt3v*b=ZzH%xba8#KupfWotSTCWG8c4#2@I(|D6 zsD6afS^+=wS>|vo11KB;=A-AwrFa4FCrmdZ>9eT#1o$r+u4kb8^~MOV=S6Fj27fw@ zise!27{7+Ts7{~v1k@&en2+V@wGH5KiW~$U>_H#$V~7781}yMdjw!aF__xXE7G`R6 z@Zw}7*zh%UYm1Yg;vDUBFYZ1ZCyoFX*tdWn3Z1Rca`7RD{~1@X@IeP8COsZ`+a>`| zB8?qCjuXEOM3cw!(YHM*oaSF`f%5{Ea{>hh5LBCY49*6y94#?!qp3e(2O7G!pibF^ zMiOXrbGAeG$BuZrl)dNF--mPd&uF|?Z%zyb9=2}*FQW$W%U0CEZZq{RXy(5cO|)zu_$TN?7gK}0ko%wy zVjl;iB~35n?(IV`FJB$bqtX#HI(4?7N2Ojf?Pu_>T)rLMV;7@I?1xs_YprW-q_G|L zIGo=a*w;F2BdA4&2F=;2e+ZeiQhM!{7I!k>)MrKX@J8hC&NB1fV-Iu%Jmk>wz9M`Fy@V zT4n_0Vbm~5(-Ap%PDc0Up=iW873T@*0qEOUQ}p*k(YMx#8nkTs3feqs7MgL-BHqq+ z;wShF0e7HZYy2(!oEU@dS58BEoNPqP!5P-?^=R04dm?u(%{w2oLB;hh=j73he_t#Q zT8g+N#JNZ3C||d?18S7Cu@&#fvEy9+ei6=wQApZ4e<)hQmrKtu1_1Ew5a%XAN8H2Q zyApgNl{8m{Jilj-aI$VA&?KZ%7>V~1Gt6)rH{I}v_Vr2k9Qsz2ODobb5%i1KOdqt= ziz1jL3a+4W=hJfOoFn`$o0o+=KQ8v8^qi%Z$`}Q5Xwn*%P9_YXH(C*-opbRgsTTIW z8V464XIof0=8(56EKxrFGsV?D-**u1QBi5(21Di4*&*FwIUa>xrInLWOru|Jil`nY z7>~IpkZtS)1QV3&jf#VyVQjsD??q7&1KeV;tXh*hh72a18$^snF5IB}hV-onEDuJE76rPND{tfVKq+q8p$AR-87y;S4zpP-JqaOO8Uc?GPTOb% z=HdXt@*rkAA7EDw^U=3gla96YO=#&CmI)}pHA$`nz8*ojJ8~${z%+kC``#tRjleGq zmiGW=953Z?A=*qb3N}V%0HBQ`e@*EpY$j=ojBi2&W#0|_j(B%l{UwUKh>8tS8UVo0 zP^8RR5njXQY!uiM6l^*?!fVu^z|*g?__XWa4Xu{C zqL@ZIi>PZXwQkC?ntVP#9(X)~i@Wg|3Ny2%Q*6l;J6yU|a#i!iR+@&tw?@&iC}01I#zhs>xx=3}MJ75cTOCsUV<1o*tK3k~48 z1S(RSH^Rwuu33Az3BR>yU86yC~1#eAHl-%3_qgGnA&QER%5xg$(m>6tnNt z`Sqk@Uh@z|F`z*=jEIXode;A{$9o1KLph81M}?13hdzcsW1LBOxe2Cewqb|NB(8RJ9b@&b%1*+Gh_=qs#SNkIY%2Ps=VG`GE53FF97(ySt@EKoAC?*cKq1eLyG|y|Two$iy@zo#1Sxf_TES~N$PjCT7nX$K_g*UixOcsS+CoX+`GMDh3zBgL^5ewCK(R=!_OOo7yxL;ib@fNY^mG_ zeAn-rgBm~%MeZCLuu>WEun37r`R>%9Vh4Mv3{}vU%4h<{RFy_UcV z47RmN(Zj{4VwIG{QE4nhfwD_X6=+)Zaw*D#n`5}#3_bQf5w)=~qL4jZiz+%bg0fpG z&!W-wBhv*(rF***MakS5QTZ*2J5T_M(=ORE`|F5u0c+8YUI4pk)C$@FY@|^uXf+CQc@KqR`Bew22>uUx WE~9^I&Z(aO0000)d$GS~@0q=S`}eDLcX#7R&8fg#;ACJpPy==Xj{`pg z76F~PwJw616F_Qi11?mQ*#XP}ervxu$>@`J0}9SE)SVA73|I+VVz)WTaRSiiCSXRw z?<@q)u+SE5+!Ub4G~^ep!{2}t47Mc|ZUjiqK;Y&S-=74WW2h~uaRNxrHNY_`>zHby zAtrDFNX97OQUmq4DWITS0Sq=!&qxDx7{T2H#^-2YEzn}1u5HL@(q*8oRJai!K38L= z^8xnJ1f35~0C719_@u%5b{niK6;1&0_@d$Zwi&KZ8z%rY9|X=aT<1Rx*QbpWfSS)+ zsPh>Mb!y=R5Y1<>^UVH73w3JY9s|QU3|Nos@0;XVU_99`OXJeL6dYoI01xl z8us??@3&O17H$e?%o;=lruh#r7U-~0w-#;$=*?X0bUwhnG*Rb+8v%lhLmW8=SgQZM z!0#;8t%Vx_>iG)xI)6P)*7@KB;AakSuEqM7TC7_eHw6fX1M7exmg;{M*-mbn6+jO+ z0tny0UgrZWrwKbBoB%+!d1qR-al7UEwW<0PFcx?W7-Z4L-+_r1>rX}1M}S+g+xZ~p z0-Kg93*dU--Ii@U58Q3pMk=Z*fN98Pk8OSoY|p@sHdVX_7>dmMM`U2@1mq}K(^AC| zU=i7L{(Urg=R@@b@CD%PjBNcVBRi?6(iCte;*606TY%$%mol=aO;tvKBY?#j+PjAW zbUsu^0E-bHzpVI4hPF~s1pzDoPS4QZBf!HM+Dk>*1uzr1GGm)R&)8ln$}E7Rfje@r z+cZA^aVYCkK!4y*z=;{#-3%Ow?Ee>nvW@_^kbUO^JVAjvAId3!PXia_WcwdE+0~|O z0(d*{ogD2ym!oYh$|QhRU42ckM1Ew zy$@jDpTA6W0J8`gF-;3#Byz-hI^q(2XoBx<@A*zt6wNOK*J-z|+FS(uAo!sv0gMB_ zgg9XI)vV(rq92{wfmNDyJA`uxj09<)0{S8@S5E^UL%;K{CA#wmA_!%id*}&R ztuq2#fw|7Vh3L))__`rm4xtTrhxaC_04@iU59We@Jkvjt_1}!1v_`)_bINAqJRf03&yd)HNg*q0q^96u<0gS->${)z)&rU^|H(Rjl zXv|dq8@~X?VrLEh@fc-H?lwB28RLKB31BSps9=L971s~OPL^&*V}|2Pj_CXl zssoB`xCNjrIfw=xK_iiS02^#kTpx=5ff7e@Uc{Hc+CKucSu*&%;=23wXG`6P>yDLLH`?10Eb{Ff8PIycK!tC`)N5Fl+UPYNa13OlY zyMRsp4?F?1U}q_|3yD+_MXLq7j^6AAz8d_nkMCd8ace+Ar>X?t_5iZsYUDI`9a%&P zQwht4@ErAAPe^ zq*p5_A10#n;eY^k5$&+4OAG3!iw?zghd#=+9Zvu|ffp<^pdae>g{ULqj&v+U5v9}< zz-C~prADas82)X^u0vuh%!?}E31AcIO&eWQdkjxwXZmpn=Mgaqdji-BY_!w>RiNZu z#E5C@(54Lu#MKZ_02}Zf88%Fu@NTN`u#R+02)p13U>}n6uFHb)x5Oy(m<79z1B?s1 z;9vOJgzwzALB;^X6lGMQ;vDG+eH0I_{MncW1`%*YZopa!m~^o~gpTY%0Yt7ErC?%= zGRrO5c0}A{2L`2bb1l+*< zG}`?$9TN~_N%*W7%a9;bHvs=lSywyqxEVKS#75-C=cbf)%fiZ}U(n4S9>!qc<492AG;xQw zA^C%nxQibT+=|)(wXCd0!-vDP0Q?+-JT^{74u`w}5l9Piv(m_LH!=mZB2OCU0uLm# zI|B)YQnfvVQ;Bf>3d5!Vg7imr0|yW;0FN#tcx5NP6lV#jAtTY}FrWOY895(Vr1Qlr z1&|lhkvzmx73GS^9^@um+jpW00`M4*j0!U;M}C5(z+B+DG?i3I0DdL`A3#Qh$rLA6 zaW|6t=SB>j;;O0u{0s+9?)iHw@-#6z*A~^Y5%G~+4g3PbN9mmadQ(Hr)Q?BDSKAPg z3`fp64no4)_Cs!LYdwEnyu)r}eWg+S!y2+}+l7SD-P`l`5)ve12a;WFEATAh(Q7Mm b3jqHI^B3_s1oi2V00000NkvXXu0mjfyMibd literal 0 HcmV?d00001 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/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..def989680d 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -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: .top, + videoFile: configuration.videos["profile_badge"], + 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 { @@ -1146,6 +1165,7 @@ public class PremiumDemoScreen: ViewControllerComponentContainer { case profileBadge case animatedUserpics case appIcons + case animatedEmoji } public enum Source: Equatable { diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 752fee51db..afc00dcf19 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -99,6 +99,7 @@ enum PremiumPerk: CaseIterable { case profileBadge case animatedUserpics case appIcons + case animatedEmoji static var allCases: [PremiumPerk] { return [ @@ -112,7 +113,8 @@ enum PremiumPerk: CaseIterable { .advancedChatManagement, .profileBadge, .animatedUserpics, - .appIcons + .appIcons, + .animatedEmoji ] } @@ -150,6 +152,8 @@ enum PremiumPerk: CaseIterable { return "animated_userpics" case .appIcons: return "app_icon" + case .animatedEmoji: + return "animated_emoji" } } @@ -177,6 +181,8 @@ enum PremiumPerk: CaseIterable { return strings.Premium_Avatar case .appIcons: return strings.Premium_AppIcon + case .animatedEmoji: + return strings.Premium_AnimatedEmoji } } @@ -204,6 +210,8 @@ enum PremiumPerk: CaseIterable { return strings.Premium_AvatarInfo case .appIcons: return strings.Premium_AppIconInfo + case .animatedEmoji: + return strings.Premium_AnimatedEmojiInfo } } @@ -231,6 +239,8 @@ enum PremiumPerk: CaseIterable { return "Premium/Perk/Avatar" case .appIcons: return "Premium/Perk/AppIcon" + case .animatedEmoji: + return "Premium/Perk/AppIcon" } } } @@ -248,7 +258,8 @@ private struct PremiumIntroConfiguration { .advancedChatManagement, .profileBadge, .animatedUserpics, - .appIcons + .appIcons, + .animatedEmoji ]) } @@ -872,6 +883,7 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { UIColor(rgb: 0x7561EB), UIColor(rgb: 0x5A6EEE), UIColor(rgb: 0x548DFF), + UIColor(rgb: 0x54A3FF), UIColor(rgb: 0x54A3FF) ] @@ -943,6 +955,8 @@ private final class PremiumIntroScreenContentComponent: CombinedComponent { demoSubject = .animatedUserpics case .appIcons: demoSubject = .appIcons + case .animatedEmoji: + demoSubject = .animatedEmoji } let controller = PremiumDemoScreen( diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 7a070c170a..e3e96d764c 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -24,6 +24,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 +32,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 +41,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 +81,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) case selectivePrivacyInfo(PresentationTheme, String) case passcode(PresentationTheme, String, Bool, String) case twoStepVerification(PresentationTheme, String, String, TwoStepVerificationAccessConfiguration?) @@ -96,7 +99,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 @@ -131,24 +134,26 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { return 10 case .groupPrivacy: return 11 - case .selectivePrivacyInfo: + case .voiceMessagePrivacy: 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 +201,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): + if case let .voiceMessagePrivacy(rhsTheme, rhsText, rhsValue) = rhs, lhsTheme === rhsTheme, lhsText == rhsText, lhsValue == rhsValue { + 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 @@ -310,6 +321,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): + return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, 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): @@ -434,6 +449,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceCalls))) 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))) + entries.append(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, stringForSelectiveSettings(strings: presentationData.strings, settings: privacySettings.voiceMessages))) entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp)) } else { @@ -442,6 +458,7 @@ private func privacyAndSecurityControllerEntries(presentationData: PresentationD entries.append(.voiceCallPrivacy(presentationData.theme, presentationData.strings.Privacy_Calls, presentationData.strings.Channel_NotificationLoading)) 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(.voiceMessagePrivacy(presentationData.theme, presentationData.strings.Privacy_VoiceMessages, presentationData.strings.Channel_NotificationLoading)) entries.append(.selectivePrivacyInfo(presentationData.theme, presentationData.strings.PrivacyLastSeenSettings_GroupsAndChannelsHelp)) } @@ -582,7 +599,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 +622,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 +659,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 +682,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 +705,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 +728,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 +737,29 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting }), true) } })) + }, openVoiceMessagePrivacy: { + let signal = privacySettingsPromise.get() + |> take(1) + |> deliverOnMainQueue + currentInfoDisposable.set(signal.start(next: { [weak currentInfoDisposable] info in + 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) + } + })) }, openPasscode: { let _ = passcodeOptionsAccessController(context: context, pushController: { controller in replaceTopControllerImpl?(controller) @@ -767,7 +807,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 +846,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() } 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/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/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 87f8a9b635..c67a0b6594 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -327,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) } @@ -344,11 +345,12 @@ 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[1147243133] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentGiftPremium($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) } @@ -588,6 +590,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) } diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index 8a78bc01fc..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,1051 +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 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 .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 .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 .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_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_messageActionGiftPremium(_ reader: BufferReader) -> MessageAction? { - var _1: String? - _1 = parseString(reader) - 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.MessageAction.messageActionGiftPremium(currency: _1!, amount: _2!, months: _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 7668430ca7..47642963ed 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -1,537 +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 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) + 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 .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) + 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 .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))]) + 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_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.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 @@ -541,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 @@ -613,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 91c4c76183..d25de327ff 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,404 +274,104 @@ 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) + 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? - _3 = parseString(reader) + if Int(_1!) & Int(1 << 1) != 0 {_3 = parseString(reader) } var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - var _6: String? - _6 = parseString(reader) + 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 = _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!) + 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 @@ -501,417 +381,37 @@ public extension Api { } } public extension Api { - enum PremiumGiftOption: TypeConstructorDescription { - case premiumGiftOption(flags: Int32, months: Int32, currency: String, amount: Int64, botUrl: String, storeProduct: String?) + enum PaymentSavedCredentials: TypeConstructorDescription { + case paymentSavedCredentialsCard(id: String, title: 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): + case .paymentSavedCredentialsCard(let id, let title): if boxed { - buffer.appendInt32(1958953753) + buffer.appendInt32(-842892769) } - 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)} + serializeString(id, buffer: buffer, boxed: false) + serializeString(title, 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))]) + case .paymentSavedCredentialsCard(let id, let title): + return ("paymentSavedCredentialsCard", [("id", String(describing: id)), ("title", String(describing: title))]) } } - 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 - - 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() + public static func parse_paymentSavedCredentialsCard(_ reader: BufferReader) -> PaymentSavedCredentials? { + var _1: String? + _1 = parseString(reader) 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.PaymentSavedCredentials.paymentSavedCredentialsCard(id: _1!, title: _2!) } else { return nil @@ -921,47 +421,29 @@ 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 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 .recentMeUrlChat(let url, let chatId): + case .peerChannel(let channelId): if boxed { - buffer.appendInt32(-1294306862) + buffer.appendInt32(-1566230754) + } + serializeInt64(channelId, buffer: buffer, boxed: false) + break + case .peerChat(let chatId): + if boxed { + buffer.appendInt32(918946202) } - serializeString(url, buffer: buffer, boxed: false) 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 } @@ -969,85 +451,871 @@ 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 + } + } + + } +} +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!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api16.swift b/submodules/TelegramApi/Sources/Api16.swift index 916951a39e..830291d176 100644 --- a/submodules/TelegramApi/Sources/Api16.swift +++ b/submodules/TelegramApi/Sources/Api16.swift @@ -1,721 +1,126 @@ 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 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 .replyInlineMarkup(let rows): + case .photoCachedSize(let type, let w, let h, let bytes): if boxed { - buffer.appendInt32(1218642516) + buffer.appendInt32(35527382) } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(rows.count)) - for item in rows { - 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 { - 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 - } - } - - 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) - 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 .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 +128,802 @@ 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 + } + } + + } +} +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!) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api17.swift b/submodules/TelegramApi/Sources/Api17.swift index bf6fb0bbfc..31892c8e6f 100644 --- a/submodules/TelegramApi/Sources/Api17.swift +++ b/submodules/TelegramApi/Sources/Api17.swift @@ -1,278 +1,331 @@ public extension Api { - enum SearchResultsCalendarPeriod: TypeConstructorDescription { - case searchResultsCalendarPeriod(date: Int32, minMsgId: Int32, maxMsgId: Int32, count: Int32) + 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 .searchResultsCalendarPeriod(let date, let minMsgId, let maxMsgId, let count): + case .recentMeUrlChat(let url, let chatId): if boxed { - buffer.appendInt32(-911191137) + buffer.appendInt32(-1294306862) } - serializeInt32(date, buffer: buffer, boxed: false) - serializeInt32(minMsgId, buffer: buffer, boxed: false) - serializeInt32(maxMsgId, buffer: buffer, boxed: false) - serializeInt32(count, 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 .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 .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_searchResultsCalendarPeriod(_ reader: BufferReader) -> SearchResultsCalendarPeriod? { - 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 _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!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureCredentialsEncrypted: TypeConstructorDescription { - case secureCredentialsEncrypted(data: Buffer, hash: Buffer, secret: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureCredentialsEncrypted(let data, let hash, let secret): - if boxed { - buffer.appendInt32(871426631) - } - 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 .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_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 - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.SecureCredentialsEncrypted.secureCredentialsEncrypted(data: _1!, hash: _2!, secret: _3!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum SecureData: TypeConstructorDescription { - case secureData(data: Buffer, dataHash: Buffer, secret: Buffer) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .secureData(let data, let dataHash, let secret): - if boxed { - buffer.appendInt32(-1964327229) - } - 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 .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_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 +334,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 +820,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 737828ce5d..7f1724a2b6 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -1,1045 +1,77 @@ 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?, 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 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(-673242758) } 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)} + 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 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))]) } } - 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?, premiumGifts: [Api.PremiumGiftOption]?) - - 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, let premiumGifts): - if boxed { - buffer.appendInt32(-994968513) - } - 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 - } - } - - 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 + _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() + if Int(_1!) & Int(1 << 4) != 0 {_9 = reader.readInt32() } var _10: Int32? - if Int(_1!) & Int(1 << 11) != 0 {_10 = reader.readInt32() } + _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(-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() 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 = _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!) } else { return nil @@ -1049,289 +81,1983 @@ 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 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 .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 .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_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 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 .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))]) + } + } + + 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 @@ -1340,50 +2066,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? @@ -1391,7 +3186,298 @@ 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_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..9dadf48c72 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,1209 @@ 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?, 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) + } + 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 1f202e0395..58fa0773fb 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -1,7510 +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 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 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(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() -> (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..1f202e0395 --- /dev/null +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -0,0 +1,7510 @@ +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 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() -> (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 { + 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/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 62718b4098..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) @@ -456,16 +636,18 @@ public extension Api { } public extension Api { enum InputStorePaymentPurpose: TypeConstructorDescription { - case inputStorePaymentGiftPremium(userId: Api.InputUser) + 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): + case .inputStorePaymentGiftPremium(let userId, let currency, let amount): if boxed { - buffer.appendInt32(1147243133) + 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 { @@ -478,8 +660,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .inputStorePaymentGiftPremium(let userId): - return ("inputStorePaymentGiftPremium", [("userId", String(describing: userId))]) + 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))]) } @@ -490,9 +672,15 @@ public extension Api { 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 - if _c1 { - return Api.InputStorePaymentPurpose.inputStorePaymentGiftPremium(userId: _1!) + 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 @@ -818,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/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift b/submodules/TelegramCore/Sources/ApiUtils/TelegramMediaFile.swift index a15122379f..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 } } } 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/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_CachedUserData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift index f3c71f42c1..fb0366c200 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedUserData.swift @@ -101,6 +101,7 @@ public final class CachedUserData: CachedPeerData { public let themeEmoticon: String? public let photo: TelegramMediaImage? public let premiumGiftOptions: [CachedPremiumGiftOption] + public let voiceMessagesAvailable: Bool public let peerIds: Set public let messageIds: Set @@ -122,11 +123,12 @@ public final class CachedUserData: CachedPeerData { 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?, premiumGiftOptions: [CachedPremiumGiftOption]) { + 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 @@ -142,6 +144,7 @@ public final class CachedUserData: CachedPeerData { self.themeEmoticon = themeEmoticon self.photo = photo self.premiumGiftOptions = premiumGiftOptions + self.voiceMessagesAvailable = voiceMessagesAvailable self.peerIds = Set() @@ -184,6 +187,7 @@ public final class CachedUserData: CachedPeerData { } self.premiumGiftOptions = decoder.decodeObjectArrayWithDecoderForKey("pgo") as [CachedPremiumGiftOption] + self.voiceMessagesAvailable = decoder.decodeInt32ForKey("vma", orElse: 0) != 0 self.peerIds = Set() @@ -240,6 +244,7 @@ public final class CachedUserData: CachedPeerData { } encoder.encodeObjectArray(self.premiumGiftOptions, forKey: "pgo") + encoder.encodeInt32(self.voiceMessagesAvailable ? 1 : 0, forKey: "vma") } public func isEqual(to: CachedPeerData) -> Bool { @@ -254,66 +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 && self.premiumGiftOptions == other.premiumGiftOptions + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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, premiumGiftOptions: self.premiumGiftOptions) + 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) + 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_Namespaces.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift index acd5448e77..ed9704bbe5 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -46,6 +46,7 @@ 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 struct OrderedItemList { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift index df9fbc310d..878138d829 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_TelegramMediaFile.swift @@ -19,6 +19,7 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { case animatedEmoji case dice(String) case animatedEmojiAnimations + case premiumGifts public init(decoder: PostboxDecoder) { switch decoder.decodeInt32ForKey("r", orElse: 0) { @@ -32,6 +33,8 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { self = .dice(decoder.decodeStringForKey("e", orElse: "🎲")) case 4: self = .animatedEmojiAnimations + case 5: + self = .premiumGifts default: self = .name("") assertionFailure() @@ -53,6 +56,8 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { self = .dice((try? container.decode(String.self, forKey: "e")) ?? "🎲") case 4: self = .animatedEmojiAnimations + case 5: + self = .premiumGifts default: self = .name("") assertionFailure() @@ -75,6 +80,8 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { encoder.encodeString(emoji, forKey: "e") case .animatedEmojiAnimations: encoder.encodeInt32(4, forKey: "r") + case .premiumGifts: + encoder.encodeInt32(5, forKey: "r") } } @@ -96,6 +103,8 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { 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") } } @@ -131,6 +140,12 @@ public enum StickerPackReference: PostboxCoding, Hashable, Equatable, Codable { } else { return false } + case .premiumGifts: + if case .premiumGifts = rhs { + return true + } else { + return false + } } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index 3ac874fe5d..a0b5eb27aa 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -12,7 +12,7 @@ public enum AssignAppStoreTransactionError { public enum AppStoreTransactionPurpose { case subscription - case gift(EnginePeer.Id) + case gift(peerId: EnginePeer.Id, currency: String, amount: Int64) case restore } @@ -25,11 +25,11 @@ func _internal_sendAppStoreReceipt(account: Account, receipt: Data, purpose: App flags |= (1 << 0) } purposeSignal = .single(.inputStorePaymentPremiumSubscription(flags: flags)) - case let .gift(peerId): + 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)) + return .single(.inputStorePaymentGiftPremium(userId: inputUser, currency: currency, amount: amount)) } else { return .complete() } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index a8f0eb91ea..acf57cc6df 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -239,11 +239,13 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee 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 @@ -271,6 +273,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee .withUpdatedThemeEmoticon(userFullThemeEmoticon) .withUpdatedPhoto(photo) .withUpdatedPremiumGiftOptions(premiumGiftOptions) + .withUpdatedVoiceMessagesAvailable(voiceMessagesAvailable) } }) } 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 mapToSignal { result, loadRemote, previousHash in @@ -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/LoadedStickerPack.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/LoadedStickerPack.swift index 0abcc50461..a0091d4612 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 } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift index 10dc4e700a..bd5233badd 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 diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 6a2b9fa3d9..bbd8a80de0 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -5621,6 +5621,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? @@ -5642,6 +5643,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 { @@ -5683,6 +5685,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 @@ -5765,7 +5769,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) @@ -5774,6 +5778,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: { @@ -7285,6 +7290,27 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return false } + if !strongSelf.presentationInterfaceState.voiceMessagesAvailable { + if strongSelf.recordingModeFeedback == nil { + strongSelf.recordingModeFeedback = HapticFeedback() + strongSelf.recordingModeFeedback?.prepareError() + } + + strongSelf.chatDisplayNode.dismissInput() + + let context = strongSelf.context + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: context, subject: .voiceToText, action: { + let controller = PremiumIntroScreen(context: context, source: .settings) + replaceImpl?(controller) + }) + replaceImpl = { [weak controller] c in + controller?.replace(with: c) + } + strongSelf.push(controller) + return + } + let requestId = strongSelf.beginMediaRecordingRequestId let begin: () -> Void = { guard let strongSelf = self, strongSelf.beginMediaRecordingRequestId == requestId else { @@ -7313,6 +7339,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: { diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index f51919647f..173aa57700 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -1031,6 +1031,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] = [] @@ -1039,8 +1040,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() @@ -1051,8 +1052,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() @@ -1063,8 +1064,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() }))) @@ -1072,8 +1073,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 } From d5a08c6de51d7917231b539465d1d9a60db45772 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 13:47:04 +0200 Subject: [PATCH 050/113] Trigger build --- Random.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Random.txt b/Random.txt index 9851d311a9..858ae6f780 100644 --- a/Random.txt +++ b/Random.txt @@ -1 +1 @@ -d66a871d990a1084502f4856b3d66c35 +a01d873e495a71cc996d4d66c2721933 From 60df27eb5298a1fa7fe00c3ebaec5181120040ae Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 13:56:02 +0200 Subject: [PATCH 051/113] Trigger build --- Random.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Random.txt b/Random.txt index 858ae6f780..34c2b34b5c 100644 --- a/Random.txt +++ b/Random.txt @@ -1 +1 @@ -a01d873e495a71cc996d4d66c2721933 +462c8b20925f8d3f87f0ab82d25d9c2a From 42293bcf05e47da1f5c50155f00507d547342a3e Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 23:21:03 +0200 Subject: [PATCH 052/113] Temp --- .../Source/QueueLocalObject.swift | 5 + .../Sources/AnimationCache.swift | 70 +++-- .../AnimationCache/Sources/ImageData.swift | 34 +-- .../MultiAnimationRendererShaders.metal | 11 +- .../Sources/MultiAnimationMetalRenderer.swift | 247 ++++++++++-------- 5 files changed, 210 insertions(+), 157 deletions(-) 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/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 96920e9871..f5ca8fa4b2 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -5,10 +5,17 @@ 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 RequestedFormat { case rgba - case yuva + case yuva(bytesPerRow: Int) } public final class Plane { @@ -279,7 +286,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { } else { isFirstFrame = true - surface = ImageARGB(width: width, height: height) + surface = ImageARGB(width: width, height: height, bytesPerRow: alignUp(size: width * 4, align: 32)) self.currentSurface = surface } @@ -292,7 +299,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { return } } else { - yuvaSurface = ImageYUVA420(width: width, height: height) + yuvaSurface = ImageYUVA420(width: width, height: height, bytesPerRow: nil) self.currentYUVASurface = yuvaSurface } @@ -484,7 +491,7 @@ private final class AnimationCacheItemAccessor { private let durationMapping: [Double] private let totalDuration: Double - private var currentYUVASurface: ImageYUVA420 + private var currentYUVASurface: ImageYUVA420? private var currentDctData: DctData private var currentDctCoefficients: DctCoefficientsYUVA420 @@ -506,7 +513,6 @@ private final class AnimationCacheItemAccessor { self.durationMapping = durationMapping self.totalDuration = totalDuration - self.currentYUVASurface = ImageYUVA420(width: width, height: height) self.currentDctData = DctData(quality: dctQuality) self.currentDctCoefficients = DctCoefficientsYUVA420(width: width, height: height) } @@ -544,43 +550,53 @@ private final class AnimationCacheItemAccessor { frameDataOffset += dctPlane.data.count } - self.currentDctCoefficients.idct(dctData: self.currentDctData, target: self.currentYUVASurface) + let yuvaSurface: ImageYUVA420 + switch requestedFormat { + case .rgba: + if let currentYUVASurface = self.currentYUVASurface { + yuvaSurface = currentYUVASurface + } else { + yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, bytesPerRow: nil) + } + case let .yuva(preferredBytesPerRow): + yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, bytesPerRow: preferredBytesPerRow) + } + + self.currentDctCoefficients.idct(dctData: self.currentDctData, target: yuvaSurface) switch requestedFormat { case .rgba: - let currentSurface = ImageARGB(width: self.currentYUVASurface.yPlane.width, height: self.currentYUVASurface.yPlane.height) - self.currentYUVASurface.toARGB(target: currentSurface) + let currentSurface = ImageARGB(width: yuvaSurface.yPlane.width, height: yuvaSurface.yPlane.height, bytesPerRow: alignUp(size: yuvaSurface.yPlane.width * 4, align: 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: frameInfo.duration) case .yuva: - let currentYUVASurface = self.currentYUVASurface - self.currentYUVASurface = ImageYUVA420(width: currentYUVASurface.yPlane.width, height: currentYUVASurface.yPlane.height) - return AnimationCacheItemFrame( format: .yuva( y: AnimationCacheItemFrame.Plane( - data: currentYUVASurface.yPlane.data, - width: currentYUVASurface.yPlane.width, - height: currentYUVASurface.yPlane.height, - bytesPerRow: currentYUVASurface.yPlane.bytesPerRow + data: yuvaSurface.yPlane.data, + width: yuvaSurface.yPlane.width, + height: yuvaSurface.yPlane.height, + bytesPerRow: yuvaSurface.yPlane.bytesPerRow ), u: AnimationCacheItemFrame.Plane( - data: currentYUVASurface.uPlane.data, - width: currentYUVASurface.uPlane.width, - height: currentYUVASurface.uPlane.height, - bytesPerRow: currentYUVASurface.uPlane.bytesPerRow + data: yuvaSurface.uPlane.data, + width: yuvaSurface.uPlane.width, + height: yuvaSurface.uPlane.height, + bytesPerRow: yuvaSurface.uPlane.bytesPerRow ), v: AnimationCacheItemFrame.Plane( - data: currentYUVASurface.vPlane.data, - width: currentYUVASurface.vPlane.width, - height: currentYUVASurface.vPlane.height, - bytesPerRow: currentYUVASurface.vPlane.bytesPerRow + data: yuvaSurface.vPlane.data, + width: yuvaSurface.vPlane.width, + height: yuvaSurface.vPlane.height, + bytesPerRow: yuvaSurface.vPlane.bytesPerRow ), a: AnimationCacheItemFrame.Plane( - data: currentYUVASurface.aPlane.data, - width: currentYUVASurface.aPlane.width, - height: currentYUVASurface.aPlane.height, - bytesPerRow: currentYUVASurface.aPlane.bytesPerRow + data: yuvaSurface.aPlane.data, + width: yuvaSurface.aPlane.width, + height: yuvaSurface.aPlane.height, + bytesPerRow: yuvaSurface.aPlane.bytesPerRow ) ), duration: frameInfo.duration diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift index 284ef6aff2..add500560c 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -9,20 +9,20 @@ final class ImagePlane { let components: Int var data: Data - init(width: Int, height: Int, components: Int) { + init(width: Int, height: Int, components: Int, bytesPerRow: Int?) { self.width = width self.height = height - self.bytesPerRow = width * components + self.bytesPerRow = bytesPerRow ?? (width * components) self.components = components - self.data = Data(count: width * components * height) + self.data = Data(count: self.bytesPerRow * height) } } final class ImageARGB { let argbPlane: ImagePlane - init(width: Int, height: Int) { - self.argbPlane = ImagePlane(width: width, height: height, components: 4) + init(width: Int, height: Int, bytesPerRow: Int?) { + self.argbPlane = ImagePlane(width: width, height: height, components: 4, bytesPerRow: bytesPerRow) } } @@ -32,11 +32,11 @@ final class ImageYUVA420 { let vPlane: ImagePlane let aPlane: ImagePlane - init(width: Int, height: Int) { - self.yPlane = ImagePlane(width: width, height: height, components: 1) - self.uPlane = ImagePlane(width: width / 2, height: height / 2, components: 1) - self.vPlane = ImagePlane(width: width / 2, height: height / 2, components: 1) - self.aPlane = ImagePlane(width: width, height: height, components: 1) + init(width: Int, height: Int, bytesPerRow: Int?) { + self.yPlane = ImagePlane(width: width, height: height, components: 1, bytesPerRow: bytesPerRow) + self.uPlane = ImagePlane(width: width / 2, height: height / 2, components: 1, bytesPerRow: bytesPerRow) + self.vPlane = ImagePlane(width: width / 2, height: height / 2, components: 1, bytesPerRow: bytesPerRow) + self.aPlane = ImagePlane(width: width, height: height, components: 1, bytesPerRow: bytesPerRow) } } @@ -92,8 +92,8 @@ extension ImageARGB { } } - func toYUVA420() -> ImageYUVA420 { - let resultImage = ImageYUVA420(width: self.argbPlane.width, height: self.argbPlane.height) + func toYUVA420(bytesPerRow: Int?) -> ImageYUVA420 { + let resultImage = ImageYUVA420(width: self.argbPlane.width, height: self.argbPlane.height, bytesPerRow: bytesPerRow) self.toYUVA420(target: resultImage) return resultImage } @@ -125,8 +125,8 @@ extension ImageYUVA420 { } } - func toARGB() -> ImageARGB { - let resultImage = ImageARGB(width: self.yPlane.width, height: self.yPlane.height) + func toARGB(bytesPerRow: Int?) -> ImageARGB { + let resultImage = ImageARGB(width: self.yPlane.width, height: self.yPlane.height, bytesPerRow: bytesPerRow) self.toARGB(target: resultImage) return resultImage } @@ -215,14 +215,14 @@ extension DctCoefficientsYUVA420 { targetPlane.data.withUnsafeMutableBytes { bytes in let pixels = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self) - dctData.dct.inverse(withCoefficients: coefficients, pixels: pixels, width: sourcePlane.width, height: sourcePlane.height, coefficientsPerRow: targetPlane.width, bytesPerRow: targetPlane.width) + dctData.dct.inverse(withCoefficients: coefficients, pixels: pixels, width: sourcePlane.width, height: sourcePlane.height, coefficientsPerRow: targetPlane.width, bytesPerRow: targetPlane.bytesPerRow) } } } } - func idct(dctData: DctData) -> ImageYUVA420 { - let resultImage = ImageYUVA420(width: self.yPlane.width, height: self.yPlane.height) + func idct(dctData: DctData, bytesPerRow: Int?) -> ImageYUVA420 { + let resultImage = ImageYUVA420(width: self.yPlane.width, height: self.yPlane.height, bytesPerRow: bytesPerRow) self.idct(dctData: dctData, target: resultImage) return resultImage } diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal b/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal index c8a7c8c2f7..8343f753f0 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Resources/MultiAnimationRendererShaders.metal @@ -21,8 +21,6 @@ vertex Varyings multiAnimationVertex( Varyings out; constant Vertex &v = verticies[vid]; - - out.position = float4(float2(v.position), 0.0, 1.0); out.texCoord = v.texCoord; @@ -37,5 +35,12 @@ fragment half4 multiAnimationFragment( texture2d textureA[[texture(3)]] ) { constexpr sampler s(address::clamp_to_edge, filter::linear); - return half4(texture.sample(s, in.texCoord)); + + 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 index 0f9e39af6d..4237c59b90 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift @@ -62,34 +62,74 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } private final class TextureStoragePool { - let width: Int - let height: Int - let format: TextureStorage.Content.Format + 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.width = width - self.height = height - self.format = 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) { - if self.items.count < 4 { - self.items.append(content) - } else { - print("Warning: over-recycling texture storage") - } + self.items.append(content) } - func take(device: MTLDevice) -> TextureStorage.Content? { + func take() -> TextureStorage? { if self.items.isEmpty { - guard let content = TextureStorage.Content(device: device, width: self.width, height: self.height, format: format) else { - return nil - } - return content + self.lastTakeTimestamp = CFAbsoluteTimeGetCurrent() + return nil } - return self.items.removeLast() + 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) } } @@ -107,6 +147,17 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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 @@ -118,7 +169,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { bytesPerPixel = 1 pixelFormat = .r8Unorm } - let pixelRowAlignment = device.minimumLinearTextureAlignment(for: pixelFormat) + let pixelRowAlignment = Content.rowAlignment(device: device, format: format) let bytesPerRow = alignUp(size: width * bytesPerPixel, align: pixelRowAlignment) self.width = width @@ -131,7 +182,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { textureDescriptor.pixelFormat = pixelFormat textureDescriptor.width = width textureDescriptor.height = height - textureDescriptor.usage = [.renderTarget] + textureDescriptor.usage = [.shaderRead] textureDescriptor.storageMode = .shared guard let texture = device.makeTexture(descriptor: textureDescriptor) else { @@ -149,7 +200,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { textureDescriptor.pixelFormat = pixelFormat textureDescriptor.width = width textureDescriptor.height = height - textureDescriptor.usage = [.renderTarget] + textureDescriptor.usage = [.shaderRead] textureDescriptor.storageMode = buffer.storageMode guard let texture = buffer.makeTexture(descriptor: textureDescriptor, offset: 0, bytesPerRow: bytesPerRow) else { @@ -168,6 +219,8 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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) } @@ -193,64 +246,16 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.pool?.recycle(content: self.content) } } - - /*func createCGImage() -> CGImage? { - if self.isInvalidated { - return nil - } - self.isInvalidated = true - - #if targetEnvironment(simulator) - guard let data = NSMutableData(capacity: self.content.bytesPerRow * self.content.height) else { - return nil - } - data.length = self.content.bytesPerRow * self.content.height - self.content.texture.getBytes(data.mutableBytes, bytesPerRow: self.content.bytesPerRow, bytesPerImage: self.content.bytesPerRow * self.content.height, from: MTLRegion(origin: MTLOrigin(), size: MTLSize(width: self.content.width, height: self.content.height, depth: 1)), mipmapLevel: 0, slice: 0) - - guard let dataProvider = CGDataProvider(data: data as CFData) else { - return nil - } - #else - let content = self.content - let pool = self.pool - guard let dataProvider = CGDataProvider(data: Data(bytesNoCopy: self.content.buffer.contents(), count: self.content.buffer.length, deallocator: .custom { [weak pool] _, _ in - guard let pool = pool else { - return - } - pool.recycle(content: content) - }) as CFData) else { - return nil - } - #endif - - guard let image = CGImage( - width: Int(self.content.width), - height: Int(self.content.height), - bitsPerComponent: 8, - bitsPerPixel: 8 * 4, - bytesPerRow: self.content.bytesPerRow, - space: DeviceGraphicsContextSettings.shared.colorSpace, - bitmapInfo: DeviceGraphicsContextSettings.shared.transparentBitmapInfo, - provider: dataProvider, - decode: nil, - shouldInterpolate: true, - intent: .defaultIntent - ) else { - return nil - } - - return image - }*/ } private final class Frame { let timestamp: Double - let textureY: TextureStorage.Content - let textureU: TextureStorage.Content - let textureV: TextureStorage.Content - let textureA: TextureStorage.Content + let textureY: TextureStorage + let textureU: TextureStorage + let textureV: TextureStorage + let textureA: TextureStorage - init?(device: MTLDevice, textureY: TextureStorage.Content, textureU: TextureStorage.Content, textureV: TextureStorage.Content, textureA: TextureStorage.Content, data: AnimationCacheItemFrame, timestamp: Double) { + init?(device: MTLDevice, textureY: TextureStorage, textureU: TextureStorage, textureV: TextureStorage, textureA: TextureStorage, data: AnimationCacheItemFrame, timestamp: Double) { self.timestamp = timestamp self.textureY = textureY self.textureU = textureU @@ -261,10 +266,10 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { case .rgba: return nil case let .yuva(y, u, v, a): - self.textureY.replace(rgbaData: y.data, width: y.width, height: y.height, bytesPerRow: y.bytesPerRow) - self.textureU.replace(rgbaData: u.data, width: u.width, height: u.height, bytesPerRow: u.bytesPerRow) - self.textureV.replace(rgbaData: v.data, width: v.width, height: v.height, bytesPerRow: v.bytesPerRow) - self.textureA.replace(rgbaData: a.data, width: a.width, height: a.height, bytesPerRow: a.bytesPerRow) + 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) } } } @@ -292,9 +297,11 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { var targets: [TargetReference] = [] var slotIndex: Int + private let preferredBytesPerRow: Int - init(slotIndex: Int, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { + init(slotIndex: Int, preferredBytesPerRow: Int, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { self.slotIndex = slotIndex + self.preferredBytesPerRow = preferredBytesPerRow self.cache = cache self.stateUpdated = stateUpdated @@ -361,23 +368,33 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } else if !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 preferredBytesPerRow = self.preferredBytesPerRow + return LoadFrameTask(task: { [weak self] in - let frame = item.getFrame(at: timestamp, requestedFormat: .rgba) + let frame = item.getFrame(at: timestamp, requestedFormat: .yuva(bytesPerRow: preferredBytesPerRow)) + + 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, timestamp: timestamp) + } return { guard let strongSelf = self else { return } - var currentFrame: Frame? - let textureY = texturePoolFullPlane.take(device: device) - let textureU = texturePoolHalfPlane.take(device: device) - let textureV = texturePoolHalfPlane.take(device: device) - let textureA = texturePoolFullPlane.take(device: device) - 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, timestamp: timestamp) - } - strongSelf.isLoadingFrame = false if let currentFrame = currentFrame { @@ -402,6 +419,8 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { private let texturePoolFullPlane: TextureStoragePool private let texturePoolHalfPlane: TextureStoragePool + private let preferredBytesPerRow: Int + private let slotCount: Int private let slotsX: Int private let slotsY: Int @@ -449,6 +468,8 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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.preferredBytesPerRow = alignUp(size: Int(self.cellSize.width), align: TextureStorage.Content.rowAlignment(device: self.metalDevice, format: .r)) + super.init() self.device = self.metalDevice @@ -487,7 +508,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { for i in 0 ..< self.slotCount { if self.slotToItemId[i] == nil { self.slotToItemId[i] = itemId - self.itemContexts[itemId] = ItemContext(slotIndex: i, cache: cache, itemId: itemId, size: size, fetch: fetch, stateUpdated: { [weak self] in + self.itemContexts[itemId] = ItemContext(slotIndex: i, preferredBytesPerRow: self.preferredBytesPerRow, cache: cache, itemId: itemId, size: size, fetch: fetch, stateUpdated: { [weak self] in guard let strongSelf = self else { return } @@ -588,10 +609,15 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } func redraw() { - guard let commandBuffer = self.commandQueue.makeCommandBuffer() else { + guard let drawable = self.nextDrawable() else { return } - guard let drawable = self.nextDrawable() else { + + let commandQueue = self.commandQueue + let renderPipelineState = self.renderPipelineState + let cellSize = self.cellSize + + guard let commandBuffer = commandQueue.makeCommandBuffer() else { return } @@ -614,7 +640,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { return } - var usedTextures: [MultiAnimationMetalRendererImpl.TextureStorage.Content] = [] + var usedTextures: [Unmanaged] = [] var vertices: [Float] = [ -1.0, -1.0, 0.0, 0.0, @@ -623,12 +649,12 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 1.0, 1.0, 1.0, 1.0 ] - renderEncoder.setRenderPipelineState(self.renderPipelineState) + 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(self.cellSize.width), UInt32(self.cellSize.height)) + var slotSize = simd_uint2(UInt32(cellSize.width), UInt32(cellSize.height)) renderEncoder.setVertexBytes(&slotSize, length: MemoryLayout.size * 2, index: 2) for (_, itemContext) in self.itemContexts { @@ -660,14 +686,14 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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(frame.textureY) - usedTextures.append(frame.textureU) - usedTextures.append(frame.textureV) - usedTextures.append(frame.textureA) - renderEncoder.setFragmentTexture(frame.textureY.texture, index: 0) - renderEncoder.setFragmentTexture(frame.textureU.texture, index: 1) - renderEncoder.setFragmentTexture(frame.textureV.texture, index: 2) - renderEncoder.setFragmentTexture(frame.textureA.texture, 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) } @@ -692,7 +718,8 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } commandBuffer.addCompletedHandler { _ in DispatchQueue.main.async { - for _ in usedTextures { + for texture in usedTextures { + texture.release() } } } @@ -820,13 +847,13 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { for completion in completions { completion() } - } - } - - if let strongSelf = self { - for index in surfaceLayersWithTasks { - if let surfaceLayer = strongSelf.surfaceLayers[index] { - surfaceLayer.redraw() + + if let strongSelf = self { + for index in surfaceLayersWithTasks { + if let surfaceLayer = strongSelf.surfaceLayers[index] { + surfaceLayer.redraw() + } + } } } } From 0b872d86c5691c13880c68dbb999b230fd946b8d Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 13 Jul 2022 23:23:04 +0200 Subject: [PATCH 053/113] Restore default renderer --- .../TelegramUI/Sources/ChatMessageBubbleItemNode.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift index 7b4bbe4d44..7f7efef8c2 100644 --- a/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageBubbleItemNode.swift @@ -303,11 +303,11 @@ class ChatPresentationContext { }) let animationRenderer: MultiAnimationRenderer - if #available(iOS 13.0, *) { + /*if #available(iOS 13.0, *) { animationRenderer = MultiAnimationMetalRendererImpl() - } else { + } else {*/ animationRenderer = MultiAnimationRendererImpl() - } + //} self.animationRenderer = animationRenderer } From 0577baac7925bafab8f4c6a568493ae882e17ce7 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 15 Jul 2022 03:37:03 +0200 Subject: [PATCH 054/113] Emoji input improvements --- .../AttachmentTextInputPanelNode.swift | 32 ++ ...SendMessageActionSheetControllerNode.swift | 1 + .../Sources/PagerComponent.swift | 5 +- submodules/Display/Source/NavigationBar.swift | 1 + submodules/Display/Source/TextNode.swift | 57 +-- .../Sources/MTDatacenterAuthAction.m | 2 + .../Sources/MTDatacenterTransferAuthAction.m | 4 + .../MTDiscoverDatacenterAddressAction.m | 2 + submodules/MtProtoKit/Sources/MTProto.m | 6 +- .../Sources/PhotoResources.swift | 23 +- .../Postbox/Sources/TimeBasedCleanup.swift | 2 +- .../TabBarUI/Sources/TabBarController.swift | 33 +- .../Sources/Network/MultipartFetch.swift | 4 + .../PublicHeaders/ImageDCT/YuvConversion.h | 1 + .../ImageDCT/Sources/YuvConversion.m | 16 + .../Sources/AnimationCache.swift | 378 ++++++++++++++++-- .../AnimationCache/Sources/ImageData.swift | 49 ++- .../Sources/EmojiTextAttachmentView.swift | 52 ++- .../Sources/EmojiPagerContentComponent.swift | 99 ++--- .../Sources/EntityKeyboard.swift | 307 +++++++------- .../EntityKeyboardBottomPanelComponent.swift | 5 +- .../EntityKeyboardTopPanelComponent.swift | 19 +- .../Sources/GifPagerContentComponent.swift | 309 +++++++++----- .../Sources/MultiAnimationMetalRenderer.swift | 22 +- .../Sources/MultiAnimationRenderer.swift | 42 +- .../Sources/TextNodeWithEntities.swift | 45 ++- .../Sources/ChatControllerNode.swift | 23 +- .../Sources/ChatEntityKeyboardInputNode.swift | 371 +++++++++++------ .../TelegramUI/Sources/ChatInputNode.swift | 5 +- .../Sources/ChatInterfaceInputContexts.swift | 17 +- .../ChatMessageTextBubbleContentNode.swift | 44 +- .../ChatPinnedMessageTitlePanelNode.swift | 33 +- .../Sources/ChatTextInputPanelNode.swift | 8 +- .../Sources/TelegramRootController.swift | 6 +- .../Sources/ChatTextInputAttributes.swift | 84 ---- 35 files changed, 1413 insertions(+), 694 deletions(-) diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index 55d5d295a4..d747d0be7d 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -108,6 +108,33 @@ private func textInputBackgroundImage(backgroundColor: UIColor?, inputBackground } } +private final class EntityInputView: UIInputView, UIInputViewAudioFeedback { + override var inputViewStyle: UIInputView.Style { + get { + return .default + } + } + override var allowsSelfSizing: Bool { + get { + return true + } + set { + } + } + + override var intrinsicContentSize: CGSize { + CGSize(width: UIView.noIntrinsicMetric, height: 300) + } + + override func sizeToFit() { + print("sizeToFit") + } + + override func sizeThatFits(_ size: CGSize) -> CGSize { + return CGSize(width: size.width, height: 100.0) + } +} + private class CaptionEditableTextNode: EditableTextNode { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let previousAlpha = self.alpha @@ -437,6 +464,11 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS textInputNode.view.addGestureRecognizer(recognizer) textInputNode.textView.accessibilityHint = self.textPlaceholderNode.attributedText?.string + + /*let entityInputView = EntityInputView() + entityInputView.frame = CGRect(origin: CGPoint(), size: CGSize(width: 100.0, height: 100.0)) + entityInputView.backgroundColor = .blue + textInputNode.textView.inputView = entityInputView*/ } private func textFieldMaxHeight(_ maxHeight: CGFloat, metrics: LayoutMetrics) -> CGFloat { diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift index e76b1d04a2..564db9cc8b 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -656,6 +656,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 diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index aa06aec2fa..b14ec8d808 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -381,9 +381,10 @@ public final class PagerComponent TextNodeLayoutArguments { @@ -198,7 +201,8 @@ public final class TextNodeLayoutArguments { lineColor: self.lineColor, textShadowColor: self.textShadowColor, textStroke: self.textStroke, - displaySpoilers: self.displaySpoilers + displaySpoilers: self.displaySpoilers, + displayEmbeddedItemsUnderSpoilers: self.displayEmbeddedItemsUnderSpoilers ) } } @@ -972,7 +976,7 @@ open 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 @@ -1126,10 +1130,6 @@ open class TextNode: ASDisplayNode { rightOffset = ceil(secondaryRightOffset) } - if embeddedItems.count > 25 { - assert(true) - } - embeddedItems.append(TextNodeEmbeddedItem(range: NSMakeRange(startIndex, endIndex - startIndex + 1), frame: CGRect(x: min(leftOffset, rightOffset), y: descent - (ascent + descent), width: abs(rightOffset - leftOffset) + rightInset, height: ascent + descent), item: item)) } @@ -1140,9 +1140,6 @@ open class TextNode: ASDisplayNode { isLastLine = true } if isLastLine { - if attributedString.string.hasPrefix("😀") { - assert(true) - } if first { first = false } else { @@ -1224,12 +1221,6 @@ open 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)) @@ -1238,6 +1229,16 @@ open 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) + } + } } } @@ -1311,12 +1312,6 @@ open 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)) @@ -1325,6 +1320,16 @@ open 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))) @@ -1586,11 +1591,11 @@ open 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 } @@ -2231,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/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/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/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/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/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/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h index a7ceddecb9..81a3ee6569 100644 --- a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/YuvConversion.h @@ -5,5 +5,6 @@ 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/YuvConversion.m b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m index 41bd589754..0851a92c91 100644 --- a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/YuvConversion.m @@ -97,3 +97,19 @@ void combineYUVAPlanesIntoARBB(uint8_t *argb, uint8_t const *inY, uint8_t const 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 f5ca8fa4b2..09c9af7a1c 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -15,7 +15,7 @@ private func alignUp(size: Int, align: Int) -> Int { public final class AnimationCacheItemFrame { public enum RequestedFormat { case rgba - case yuva(bytesPerRow: Int) + case yuva(rowAlignment: Int) } public final class Plane { @@ -50,11 +50,17 @@ public final class AnimationCacheItem { public let numFrames: Int private let getFrameImpl: (Int, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? private let getFrameIndexImpl: (Double) -> Int + private let getFrameDurationImpl: (Int) -> Double? - public init(numFrames: Int, getFrame: @escaping (Int, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame?, getFrameIndexImpl: @escaping (Double) -> Int) { + public init(numFrames: Int, getFrame: @escaping (Int, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame?, getFrameIndexImpl: @escaping (Double) -> Int, getFrameDurationImpl: @escaping (Int) -> Double?) { self.numFrames = numFrames self.getFrameImpl = getFrame self.getFrameIndexImpl = getFrameIndexImpl + self.getFrameDurationImpl = getFrameDurationImpl + } + + public func getFrameDuration(index: Int) -> Double? { + return self.getFrameDurationImpl(index) } public func getFrame(index: Int, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { @@ -123,7 +129,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 = "" @@ -134,7 +140,7 @@ 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 func roundUp(_ numToRound: Int, multiple: Int) -> Int { @@ -209,6 +215,213 @@ private func decompressData(data: Data, range: Range, decompressedSize: Int return decompressedFrameData } +private final class AnimationCacheItemWriterInternal { + struct CompressedResult { + var path: String + } + + private struct FrameMetadata { + var offset: Int + var length: Int + var duration: Double + } + + var isCancelled: Bool = false + + private let decompressedPath: String + private let compressedPath: String + private var file: ManagedFile? + + 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 dctQuality: Int + + init?(allocateTempFile: @escaping () -> String) { + self.dctQuality = 70 + + self.decompressedPath = allocateTempFile() + self.compressedPath = allocateTempFile() + + guard let file = ManagedFile(queue: nil, path: self.decompressedPath, mode: .readwrite) else { + return nil + } + self.file = file + } + + func add(with drawingBlock: (ImageYUVA420) -> Void, proposedWidth: Int, proposedHeight: Int, duration: Double) { + if self.isFailed || self.isFinished { + return + } + + guard !self.isFailed, !self.isFinished, let file = self.file else { + return + } + + let width = roundUp(proposedWidth, multiple: 16) + let height = roundUp(proposedWidth, 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, current.quality == self.dctQuality { + dctData = current + } else { + dctData = DctData(quality: self.dctQuality) + self.currentDctData = dctData + } + + drawingBlock(yuvaSurface) + + yuvaSurface.dct(dctData: dctData, target: dctCoefficients) + + if isFirstFrame { + file.write(2 as UInt32) + + file.write(UInt32(dctCoefficients.yPlane.width)) + file.write(UInt32(dctCoefficients.yPlane.height)) + file.write(UInt32(dctData.quality)) + + self.contentLengthOffset = Int(file.position()) + file.write(0 as UInt32) + } + + let framePosition = Int(file.position()) + assert(framePosition >= 0) + var frameLength = 0 + + 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() + } + + dctPlane.data.withUnsafeBytes { bytes in + let _ = file.write(bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: bytes.count) + } + frameLength += dctPlane.data.count + } + + self.frames.append(FrameMetadata(offset: framePosition, length: frameLength, duration: duration)) + + self.contentLength += frameLength + } + + func finish() -> CompressedResult? { + var shouldComplete = false + + outer: for _ in 0 ..< 1 { + if !self.isFinished { + self.isFinished = true + shouldComplete = true + + guard let contentLengthOffset = self.contentLengthOffset, let file = self.file else { + self.isFailed = true + break outer + } + assert(contentLengthOffset >= 0) + + let metadataPosition = file.position() + file.seek(position: Int64(contentLengthOffset)) + file.write(UInt32(self.contentLength)) + + file.seek(position: metadataPosition) + file.write(UInt32(self.frames.count)) + for frame in self.frames { + file.write(UInt32(frame.offset)) + file.write(UInt32(frame.length)) + file.write(Float32(frame.duration)) + } + + if !self.frames.isEmpty { + } else { + self.isFailed = true + break outer + } + + if !self.isFailed { + self.file = nil + + file._unsafeClose() + + guard let uncompressedData = try? Data(contentsOf: URL(fileURLWithPath: self.decompressedPath), options: .alwaysMapped) else { + self.isFailed = true + break outer + } + guard let compressedData = compressData(data: uncompressedData) else { + self.isFailed = true + break outer + } + guard let compressedFile = ManagedFile(queue: nil, path: self.compressedPath, mode: .readwrite) else { + self.isFailed = true + break outer + } + compressedFile.write(Int32(uncompressedData.count)) + let _ = compressedFile.write(compressedData) + compressedFile._unsafeClose() + } + } + } + + if shouldComplete { + let _ = try? FileManager.default.removeItem(atPath: self.decompressedPath) + + if !self.isFailed { + return CompressedResult(path: self.compressedPath) + } else { + let _ = try? FileManager.default.removeItem(atPath: self.compressedPath) + + return nil + } + } else { + return nil + } + } +} + private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { struct CompressedResult { var animationPath: String @@ -246,7 +459,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { private let lock = Lock() init?(queue: Queue, allocateTempFile: @escaping () -> String, completion: @escaping (CompressedResult?) -> Void) { - self.dctQuality = 67 + self.dctQuality = 70 self.queue = queue self.decompressedPath = allocateTempFile() @@ -286,7 +499,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { } else { isFirstFrame = true - surface = ImageARGB(width: width, height: height, bytesPerRow: alignUp(size: width * 4, align: 32)) + surface = ImageARGB(width: width, height: height, rowAlignment: 32) self.currentSurface = surface } @@ -299,7 +512,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { return } } else { - yuvaSurface = ImageYUVA420(width: width, height: height, bytesPerRow: nil) + yuvaSurface = ImageYUVA420(width: width, height: height, rowAlignment: nil) self.currentYUVASurface = yuvaSurface } @@ -556,17 +769,17 @@ private final class AnimationCacheItemAccessor { if let currentYUVASurface = self.currentYUVASurface { yuvaSurface = currentYUVASurface } else { - yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, bytesPerRow: nil) + yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, rowAlignment: nil) } - case let .yuva(preferredBytesPerRow): - yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, bytesPerRow: preferredBytesPerRow) + case let .yuva(preferredRowAlignment): + yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, rowAlignment: preferredRowAlignment) } self.currentDctCoefficients.idct(dctData: self.currentDctData, target: yuvaSurface) switch requestedFormat { case .rgba: - let currentSurface = ImageARGB(width: yuvaSurface.yPlane.width, height: yuvaSurface.yPlane.height, bytesPerRow: alignUp(size: yuvaSurface.yPlane.width * 4, align: 32)) + let currentSurface = ImageARGB(width: yuvaSurface.yPlane.width, height: yuvaSurface.yPlane.height, rowAlignment: 32) yuvaSurface.toARGB(target: currentSurface) self.currentYUVASurface = yuvaSurface @@ -619,6 +832,14 @@ private final class AnimationCacheItemAccessor { } return self.durationMapping.count - 1 } + + func getFrameDuration(index: Int) -> Double? { + if index < self.durationMapping.count { + return self.durationMapping[index] + } else { + return nil + } + } } private func readUInt32(data: Data, offset: Int) -> UInt32 { @@ -747,9 +968,100 @@ private func loadItem(path: String) -> AnimationCacheItem? { return itemAccessor.getFrame(index: index, requestedFormat: requestedFormat) }, getFrameIndexImpl: { duration in return itemAccessor.getFrameIndex(duration: duration) + }, getFrameDurationImpl: { index in + return itemAccessor.getFrameDuration(index: index) }) } +private func adaptItemFromHigherResolution(itemPath: String, width: Int, height: Int, itemDirectoryPath: String, higherResolutionPath: String, allocateTempFile: @escaping () -> String) -> AnimationCacheItem? { + guard let higherResolutionItem = loadItem(path: higherResolutionPath) else { + return nil + } + guard let writer = AnimationCacheItemWriterInternal(allocateTempFile: allocateTempFile) else { + return nil + } + + for i in 0 ..< higherResolutionItem.numFrames { + guard let duration = higherResolutionItem.getFrameDuration(index: i) else { + break + } + writer.add(with: { yuva in + guard let frame = higherResolutionItem.getFrame(index: i, requestedFormat: .yuva(rowAlignment: yuva.yPlane.rowAlignment)) else { + return + } + switch frame.format { + case .rgba: + return + 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) + } + }, proposedWidth: width, proposedHeight: height, duration: duration) + } + + guard let result = writer.finish() else { + return nil + } + 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 = loadItem(path: itemPath) else { + return nil + } + return item +} + +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 { @@ -789,7 +1101,7 @@ public final class AnimationCacheImpl: AnimationCache { } func get(sourceId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, updateResult: @escaping (AnimationCacheItemResult) -> Void) -> Disposable { - let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId + "-\(Int(size.width))x\(Int(size.height))")) + 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" @@ -878,43 +1190,58 @@ public final class AnimationCacheImpl: AnimationCache { } } - static func getFirstFrameSynchronously(basePath: String, sourceId: String, size: CGSize) -> AnimationCacheItem? { - let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId + "-\(Int(size.width))x\(Int(size.height))")) + 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: itemFirstFramePath) { return loadItem(path: itemFirstFramePath) - } else { - return nil } + + 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, completion: @escaping (AnimationCacheItem?) -> Void) -> Disposable { - let sourceIdPath = itemSubpath(hashString: md5Hash(sourceId + "-\(Int(size.width))x\(Int(size.height))")) + 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 = loadItem(path: itemFirstFramePath) { completion(item) - - return EmptyDisposable - } else { - completion(nil) - 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) }) @@ -939,15 +1266,16 @@ public final class AnimationCacheImpl: AnimationCache { } public func getFirstFrameSynchronously(sourceId: String, size: CGSize) -> AnimationCacheItem? { - return Impl.getFirstFrameSynchronously(basePath: self.basePath, sourceId: sourceId, size: size) + 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, completion: completion)) + 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 index add500560c..6a31392a13 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -2,27 +2,46 @@ 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, bytesPerRow: Int?) { + init(width: Int, height: Int, components: Int, rowAlignment: Int?) { self.width = width self.height = height - self.bytesPerRow = bytesPerRow ?? (width * components) + 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, bytesPerRow: Int?) { - self.argbPlane = ImagePlane(width: width, height: height, components: 4, bytesPerRow: bytesPerRow) + init(width: Int, height: Int, rowAlignment: Int?) { + self.argbPlane = ImagePlane(width: width, height: height, components: 4, rowAlignment: rowAlignment) } } @@ -32,11 +51,11 @@ final class ImageYUVA420 { let vPlane: ImagePlane let aPlane: ImagePlane - init(width: Int, height: Int, bytesPerRow: Int?) { - self.yPlane = ImagePlane(width: width, height: height, components: 1, bytesPerRow: bytesPerRow) - self.uPlane = ImagePlane(width: width / 2, height: height / 2, components: 1, bytesPerRow: bytesPerRow) - self.vPlane = ImagePlane(width: width / 2, height: height / 2, components: 1, bytesPerRow: bytesPerRow) - self.aPlane = ImagePlane(width: width, height: height, components: 1, bytesPerRow: bytesPerRow) + 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) } } @@ -92,8 +111,8 @@ extension ImageARGB { } } - func toYUVA420(bytesPerRow: Int?) -> ImageYUVA420 { - let resultImage = ImageYUVA420(width: self.argbPlane.width, height: self.argbPlane.height, bytesPerRow: 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 } @@ -125,8 +144,8 @@ extension ImageYUVA420 { } } - func toARGB(bytesPerRow: Int?) -> ImageARGB { - let resultImage = ImageARGB(width: self.yPlane.width, height: self.yPlane.height, bytesPerRow: 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 } @@ -221,8 +240,8 @@ extension DctCoefficientsYUVA420 { } } - func idct(dctData: DctData, bytesPerRow: Int?) -> ImageYUVA420 { - let resultImage = ImageYUVA420(width: self.yPlane.width, height: self.yPlane.height, bytesPerRow: 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/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index 90f7314679..2e0f126b61 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -30,7 +30,6 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } private let context: AccountContext - private let groupId: String private let emoji: ChatTextInputTextCustomEmojiAttribute private let cache: AnimationCache private let renderer: MultiAnimationRenderer @@ -39,6 +38,8 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { 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? @@ -54,9 +55,8 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } } - public init(context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) { + public init(context: AccountContext, attemptSynchronousLoad: Bool, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor, pointSize: CGSize) { self.context = context - self.groupId = groupId self.emoji = emoji self.cache = cache self.renderer = renderer @@ -123,9 +123,10 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { self.file = file if attemptSynchronousLoad { - if !self.renderer.loadFirstFrameSynchronously(groupId: self.groupId, target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize) { + 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 } } @@ -133,10 +134,10 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } else { let pointSize = self.pointSize let placeholderColor = self.placeholderColor - self.loadDisposable = self.renderer.loadFirstFrame(groupId: self.groupId, target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, completion: { [weak self] result in + 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, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: placeholderColor) + 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 { @@ -144,6 +145,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } if let image = image { strongSelf.contents = image.cgImage + strongSelf.isDisplayingPlaceholder = true } strongSelf.loadAnimation() } @@ -165,7 +167,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { let context = self.context if file.isAnimatedSticker || file.isVideoEmoji { - self.disposable = renderer.add(groupId: self.groupId, target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, fetch: { size, writer in + 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 @@ -192,7 +194,7 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { } }) } else { - self.disposable = renderer.add(groupId: self.groupId, target: self, cache: self.cache, itemId: file.resource.id.stringRepresentation, size: self.pixelSize, fetch: { size, writer in + 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 @@ -210,13 +212,45 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { }) } } + + 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, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { - self.contentLayer = InlineStickerItemLayer(context: context, groupId: "textInputView", attemptSynchronousLoad: true, emoji: emoji, file: file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: 24.0, height: 24.0)) + self.contentLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: true, emoji: emoji, file: file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: 24.0, height: 24.0)) super.init(frame: CGRect()) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 09fd0b9db5..903aa9d4d6 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -537,12 +537,11 @@ public final class EmojiPagerContentComponent: Component { } } private(set) var displayPlaceholder: Bool = false - let onUpdateDisplayPlaceholder: (Bool) -> Void + let onUpdateDisplayPlaceholder: (Bool, Double) -> Void init( item: Item, context: AccountContext, - groupId: String, attemptSynchronousLoad: Bool, file: TelegramMediaFile?, staticEmoji: String?, @@ -552,7 +551,7 @@ public final class EmojiPagerContentComponent: Component { blurredBadgeColor: UIColor, displayPremiumBadgeIfAvailable: Bool, pointSize: CGSize, - onUpdateDisplayPlaceholder: @escaping (Bool) -> Void + onUpdateDisplayPlaceholder: @escaping (Bool, Double) -> Void ) { self.item = item self.file = file @@ -573,7 +572,7 @@ public final class EmojiPagerContentComponent: Component { return } - strongSelf.disposable = renderer.add(groupId: groupId, target: strongSelf, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, fetch: { size, writer in + 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 @@ -604,13 +603,13 @@ public final class EmojiPagerContentComponent: Component { } if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { + if !renderer.loadFirstFrameSynchronously(target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { self.updateDisplayPlaceholder(displayPlaceholder: true) } loadAnimation() } else { - let _ = renderer.loadFirstFrame(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { [weak self] success in + let _ = renderer.loadFirstFrame(target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { [weak self] success in loadAnimation() if !success { @@ -682,7 +681,7 @@ public final class EmojiPagerContentComponent: Component { self.placeholderColor = layer.placeholderColor self.size = layer.size - self.onUpdateDisplayPlaceholder = { _ in } + self.onUpdateDisplayPlaceholder = { _, _ in } super.init(layer: layer) } @@ -718,47 +717,17 @@ public final class EmojiPagerContentComponent: Component { } self.displayPlaceholder = displayPlaceholder - self.onUpdateDisplayPlaceholder(displayPlaceholder) + self.onUpdateDisplayPlaceholder(displayPlaceholder, 0.0) + } + + override func transitionToContents(_ contents: AnyObject) { + self.contents = contents - /*if displayPlaceholder { - if self.placeholderView == nil { - self.placeholderView = PortalView() - if let placeholderView = self.placeholderView, let shimmerView = self.shimmerView { - self.addSublayer(placeholderView.view.layer) - placeholderView.view.frame = self.bounds - shimmerView.addPortal(view: placeholderView) - } - } - if self.placeholderMaskLayer == nil { - self.placeholderMaskLayer = SimpleLayer() - self.placeholderView?.view.layer.mask = self.placeholderMaskLayer - } - let file = self.file - let size = self.size - //let placeholderColor = self.placeholderColor - - Queue.concurrentDefaultQueue().async { [weak self] in - if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: size, imageSize: file.dimensions?.cgSize ?? CGSize(width: 512.0, height: 512.0), backgroundColor: nil, foregroundColor: .black) { - Queue.mainQueue().async { - guard let strongSelf = self else { - return - } - - if strongSelf.displayPlaceholder { - strongSelf.placeholderMaskLayer?.contents = image.cgImage - } - } - } - } - } else { - if let placeholderView = self.placeholderView { - self.placeholderView = nil - placeholderView.view.layer.removeFromSuperlayer() - } - if let _ = self.placeholderMaskLayer { - self.placeholderMaskLayer = nil - } - }*/ + if self.displayPlaceholder { + self.displayPlaceholder = false + self.onUpdateDisplayPlaceholder(false, 0.2) + self.animateAlpha(from: 0.0, to: 1.0, duration: 0.18) + } } } @@ -790,6 +759,7 @@ public final class EmojiPagerContentComponent: Component { 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] = [:] @@ -812,12 +782,13 @@ public final class EmojiPagerContentComponent: Component { override init(frame: CGRect) { self.shimmerHostView = PortalSourceView() - self.standaloneShimmerEffect = StandaloneShimmerEffect() self.scrollView = ContentScrollView() self.scrollView.layer.anchorPoint = CGPoint() + self.placeholdersContainerView = UIView() + super.init(frame: frame) self.shimmerHostView.alpha = 0.0 @@ -842,6 +813,8 @@ public final class EmojiPagerContentComponent: Component { self.scrollView.clipsToBounds = 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 @@ -1404,7 +1377,6 @@ public final class EmojiPagerContentComponent: Component { itemLayer = ItemLayer( item: item, context: component.context, - groupId: "keyboard-\(Int(itemLayout.nativeItemSize))", attemptSynchronousLoad: attemptSynchronousLoads, file: item.file, staticEmoji: item.staticEmoji, @@ -1414,7 +1386,7 @@ public final class EmojiPagerContentComponent: Component { blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), displayPremiumBadgeIfAvailable: itemGroup.displayPremiumBadges, pointSize: itemNativeFitSize, - onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder in + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { return } @@ -1432,7 +1404,7 @@ public final class EmojiPagerContentComponent: Component { size: itemNativeFitSize ) strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView - strongSelf.scrollView.insertSubview(placeholderView, at: 0) + strongSelf.placeholdersContainerView.addSubview(placeholderView) } placeholderView.frame = itemLayer.frame placeholderView.update(size: placeholderView.bounds.size) @@ -1442,9 +1414,20 @@ public final class EmojiPagerContentComponent: Component { } else { if let placeholderView = strongSelf.visibleItemPlaceholderViews[itemId] { strongSelf.visibleItemPlaceholderViews.removeValue(forKey: itemId) - placeholderView.removeFromSuperview() - strongSelf.updateShimmerIfNeeded() + 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() + } } } } @@ -1471,7 +1454,7 @@ public final class EmojiPagerContentComponent: Component { } } else if updateItemLayerPlaceholder { if itemLayer.displayPlaceholder { - itemLayer.onUpdateDisplayPlaceholder(true) + itemLayer.onUpdateDisplayPlaceholder(true, 0.0) } } @@ -1479,6 +1462,7 @@ public final class EmojiPagerContentComponent: Component { } } + var removedPlaceholerViews = false var removedIds: [ItemLayer.Key] = [] for (id, itemLayer) in self.visibleItemLayers { if !validIds.contains(id) { @@ -1491,6 +1475,7 @@ public final class EmojiPagerContentComponent: Component { if let view = self.visibleItemPlaceholderViews.removeValue(forKey: id) { view.removeFromSuperview() + removedPlaceholerViews = true } } @@ -1527,13 +1512,17 @@ public final class EmojiPagerContentComponent: Component { self.visibleGroupPremiumButtons.removeValue(forKey: id) } + if removedPlaceholerViews { + self.updateShimmerIfNeeded() + } + if let topVisibleGroupId = topVisibleGroupId { self.activeItemUpdated?.invoke((topVisibleGroupId, .immediate)) } } private func updateShimmerIfNeeded() { - if self.visibleItemPlaceholderViews.isEmpty { + if self.placeholdersContainerView.subviews.isEmpty { self.standaloneShimmerEffect.layer = nil } else { self.standaloneShimmerEffect.layer = self.shimmerHostView.layer diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 33c1f5cbfc..e68b3ab752 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -76,8 +76,8 @@ public final class EntityKeyboardComponent: Component { public let theme: PresentationTheme public let bottomInset: CGFloat public let emojiContent: EmojiPagerContentComponent - public let stickerContent: EmojiPagerContentComponent - public let gifContent: GifPagerContentComponent + public let stickerContent: EmojiPagerContentComponent? + public let gifContent: GifPagerContentComponent? public let availableGifSearchEmojies: [GifSearchEmoji] public let defaultToEmojiTab: Bool public let externalTopPanelContainer: PagerExternalTopPanelContainer? @@ -94,8 +94,8 @@ public final class EntityKeyboardComponent: Component { theme: PresentationTheme, bottomInset: CGFloat, emojiContent: EmojiPagerContentComponent, - stickerContent: EmojiPagerContentComponent, - gifContent: GifPagerContentComponent, + stickerContent: EmojiPagerContentComponent?, + gifContent: GifPagerContentComponent?, availableGifSearchEmojies: [GifSearchEmoji], defaultToEmojiTab: Bool, externalTopPanelContainer: PagerExternalTopPanelContainer?, @@ -201,170 +201,179 @@ public final class EntityKeyboardComponent: Component { var contentAccessoryRightButtons: [AnyComponentWithIdentity] = [] let gifsContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() - contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(component.gifContent))) - var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] - //TODO:localize - topGifItems.append(EntityKeyboardTopPanelComponent.Item( - id: "recent", - isReorderable: false, - content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: "Chat/Input/Media/RecentTabIcon", - theme: component.theme, - title: "Recent", - pressed: { [weak self] in - self?.component?.switchToGifSubject(.recent) - } - )) - )) - topGifItems.append(EntityKeyboardTopPanelComponent.Item( - id: "trending", - isReorderable: false, - content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: "Chat/Input/Media/TrendingGifs", - theme: component.theme, - title: "Trending", - pressed: { [weak self] in - self?.component?.switchToGifSubject(.trending) - } - )) - )) - for emoji in component.availableGifSearchEmojies { + let stickersContentItemIdUpdated = ActionSlot<(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] = [] + //TODO:localize topGifItems.append(EntityKeyboardTopPanelComponent.Item( - id: emoji.emoji, + id: "recent", isReorderable: false, - content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( - context: component.stickerContent.context, - file: emoji.file, - animationCache: component.stickerContent.animationCache, - animationRenderer: component.stickerContent.animationRenderer, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: "Chat/Input/Media/RecentTabIcon", theme: component.theme, - title: emoji.title, + title: "Recent", pressed: { [weak self] in - self?.component?.switchToGifSubject(.emojiSearch(emoji.emoji)) + self?.component?.switchToGifSubject(.recent) } )) )) - } - let defaultActiveGifItemId: AnyHashable - switch component.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, - defaultActiveItemId: defaultActiveGifItemId, - activeContentItemIdUpdated: gifsContentItemIdUpdated, - reorderItems: { _ in + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: "trending", + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: "Chat/Input/Media/TrendingGifs", + theme: component.theme, + title: "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, + animationCache: component.emojiContent.animationCache, + animationRenderer: component.emojiContent.animationRenderer, + theme: component.theme, + title: emoji.title, + pressed: { [weak self] in + self?.component?.switchToGifSubject(.emojiSearch(emoji.emoji)) + } + )) + )) } - )))) - contentIcons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/EntityInputGifsIcon", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: nil - )))) - contentAccessoryLeftButtons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(Button( - content: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/EntityInputSearchIcon", + 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, + defaultActiveItemId: defaultActiveGifItemId, + activeContentItemIdUpdated: gifsContentItemIdUpdated, + reorderItems: { _ in + } + )))) + contentIcons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputGifsIcon", tintColor: component.theme.chat.inputMediaPanel.panelIconColor, maxSize: nil - )), - action: { [weak self] in - self?.openSearch() - } - ).minSize(CGSize(width: 38.0, height: 38.0))))) - - var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] - for itemGroup in component.stickerContent.itemGroups { - if let id = itemGroup.supergroupId.base as? String { - let iconMapping: [String: String] = [ - "saved": "Chat/Input/Media/SavedStickersTabIcon", - "recent": "Chat/Input/Media/RecentTabIcon", - "premium": "Chat/Input/Media/PremiumIcon" - ] - let titleMapping: [String: String] = [ - "saved": "Saved", - "recent": "Recent", - "premium": "Premium" - ] - if let iconName = iconMapping[id], let title = titleMapping[id] { - topStickerItems.append(EntityKeyboardTopPanelComponent.Item( - id: itemGroup.supergroupId, - isReorderable: false, - content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: iconName, - theme: component.theme, - title: title, - pressed: { [weak self] in - self?.scrollToItemGroup(contentId: "stickers", groupId: itemGroup.supergroupId, subgroupId: nil) - } - )) - )) + )))) + 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() } - } else { - if !itemGroup.items.isEmpty { - if let file = itemGroup.items[0].file { + ).minSize(CGSize(width: 38.0, height: 38.0))))) + } + + if let stickerContent = component.stickerContent { + var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] + for itemGroup in stickerContent.itemGroups { + if let id = itemGroup.supergroupId.base as? String { + let iconMapping: [String: String] = [ + "saved": "Chat/Input/Media/SavedStickersTabIcon", + "recent": "Chat/Input/Media/RecentTabIcon", + "premium": "Chat/Input/Media/PremiumIcon" + ] + let titleMapping: [String: String] = [ + "saved": "Saved", + "recent": "Recent", + "premium": "Premium" + ] + if let iconName = iconMapping[id], let title = titleMapping[id] { topStickerItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.supergroupId, - isReorderable: true, - content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( - context: component.stickerContent.context, - file: file, - animationCache: component.stickerContent.animationCache, - animationRenderer: component.stickerContent.animationRenderer, + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: iconName, theme: component.theme, - title: itemGroup.title ?? "", + 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: true, + content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( + context: stickerContent.context, + file: file, + 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, + activeContentItemIdUpdated: stickersContentItemIdUpdated, + reorderItems: { [weak self] items in + guard let strongSelf = self else { + return + } + strongSelf.reorderPacks(category: .stickers, items: items) + } + )))) + contentIcons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(BundleIconComponent( + name: "Chat/Input/Media/EntityInputStickersIcon", + tintColor: component.theme.chat.inputMediaPanel.panelIconColor, + maxSize: nil + )))) + 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.inputInteraction.openStickerSettings() + } + ).minSize(CGSize(width: 38.0, height: 38.0))))) } - let stickersContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() - contents.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(component.stickerContent))) - contentTopPanels.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(EntityKeyboardTopPanelComponent( - theme: component.theme, - items: topStickerItems, - activeContentItemIdUpdated: stickersContentItemIdUpdated, - reorderItems: { [weak self] items in - guard let strongSelf = self else { - return - } - strongSelf.reorderPacks(category: .stickers, items: items) - } - )))) - contentIcons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/EntityInputStickersIcon", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: nil - )))) - 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: { - component.stickerContent.inputInteraction.openStickerSettings() - } - ).minSize(CGSize(width: 38.0, height: 38.0))))) let emojiContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() contents.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(component.emojiContent))) @@ -521,10 +530,6 @@ public final class EntityKeyboardComponent: Component { ) transition.setFrame(view: self.pagerView, frame: CGRect(origin: CGPoint(), size: pagerSize)) - if transition.userData(MarkInputCollapsed.self) != nil { - self.searchComponent = nil - } - if let searchComponent = self.searchComponent { var animateIn = false let searchView: ComponentHostView @@ -546,7 +551,7 @@ public final class EntityKeyboardComponent: Component { component: AnyComponent(searchComponent), environment: { EntitySearchContentEnvironment( - context: component.stickerContent.context, + context: component.emojiContent.context, theme: component.theme, deviceMetrics: component.deviceMetrics ) @@ -669,7 +674,7 @@ public final class EntityKeyboardComponent: Component { case .emoji: namespace = Namespaces.ItemCollection.CloudEmojiPacks } - let _ = (component.stickerContent.context.engine.stickers.reorderStickerPacks(namespace: namespace, itemIds: currentIds) + let _ = (component.emojiContent.context.engine.stickers.reorderStickerPacks(namespace: namespace, itemIds: currentIds) |> deliverOnMainQueue).start(completed: { [weak self] in guard let strongSelf = self else { return diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift index ff57b95ec9..495748e37b 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift @@ -313,7 +313,10 @@ final class EntityKeyboardBottomPanelComponent: Component { 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) + 2.0) + var nextIconOrigin = CGPoint(x: floor((availableSize.width - iconTotalSize.width) / 2.0), y: floor((intrinsicHeight - iconTotalSize.height) / 2.0)) + if component.bottomInset > 0.0 { + nextIconOrigin.y += 2.0 + } for icon in panelEnvironment.contentIcons { guard let iconInfo = iconInfos[icon.id], let iconView = self.iconViews[icon.id] else { continue diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index c8ac47cfe5..7e2fe8382a 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -100,7 +100,6 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { subgroupId: nil ), context: component.context, - groupId: "topPanel", attemptSynchronousLoad: false, file: component.file, staticEmoji: nil, @@ -110,18 +109,18 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { blurredBadgeColor: .clear, displayPremiumBadgeIfAvailable: false, pointSize: CGSize(width: 44.0, height: 44.0), - onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder in + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { return } - strongSelf.updateDisplayPlaceholder(displayPlaceholder: displayPlaceholder) + strongSelf.updateDisplayPlaceholder(displayPlaceholder: displayPlaceholder, duration: duration) } ) self.itemLayer = itemLayer self.layer.addSublayer(itemLayer) if itemLayer.displayPlaceholder { - self.updateDisplayPlaceholder(displayPlaceholder: true) + self.updateDisplayPlaceholder(displayPlaceholder: true, duration: 0.0) } } @@ -170,7 +169,7 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { return availableSize } - private func updateDisplayPlaceholder(displayPlaceholder: Bool) { + private func updateDisplayPlaceholder(displayPlaceholder: Bool, duration: Double) { if displayPlaceholder { if self.placeholderView == nil, let component = self.component { let placeholderView = EmojiPagerContentComponent.View.ItemPlaceholderView( @@ -188,7 +187,15 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { } else { if let placeholderView = self.placeholderView { self.placeholderView = nil - placeholderView.removeFromSuperview() + + 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() + } } } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index b18ac64c11..a31a717d95 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -19,10 +19,11 @@ import SoftwareVideo import AVFoundation import PhotoResources import ContextUI +import ShimmerEffect private class GifVideoLayer: AVSampleBufferDisplayLayer { private let context: AccountContext - private let file: TelegramMediaFile + private let file: TelegramMediaFile? private var frameManager: SoftwareVideoLayerFrameManager? @@ -56,7 +57,7 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer { } } - init(context: AccountContext, file: TelegramMediaFile, synchronousLoad: Bool) { + init(context: AccountContext, file: TelegramMediaFile?, synchronousLoad: Bool) { self.context = context self.file = file @@ -64,29 +65,31 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer { self.videoGravity = .resizeAspectFill - if let dimensions = file.dimensions { - self.thumbnailDisposable = (mediaGridMessageVideo(postbox: context.account.postbox, videoReference: .savedGif(media: self.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?() - } + 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 } - } else { - strongSelf.setupVideo() - } - }) - } else { - self.setupVideo() + 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() + } } } @@ -103,7 +106,10 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer { } private func setupVideo() { - let frameManager = SoftwareVideoLayerFrameManager(account: self.context.account, fileReference: .savedGif(media: self.file), layerHolder: nil, layer: self) + 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 { @@ -127,13 +133,16 @@ public final class GifPagerContentComponent: Component { public final class InputInteraction { public let performItemAction: (Item, UIView, CGRect) -> Void public let openGifContextMenu: (TelegramMediaFile, UIView, CGRect, ContextGesture, Bool) -> Void + public let loadMore: (String) -> Void public init( performItemAction: @escaping (Item, UIView, CGRect) -> Void, - openGifContextMenu: @escaping (TelegramMediaFile, UIView, CGRect, ContextGesture, Bool) -> Void + openGifContextMenu: @escaping (TelegramMediaFile, UIView, CGRect, ContextGesture, Bool) -> Void, + loadMore: @escaping (String) -> Void ) { self.performItemAction = performItemAction self.openGifContextMenu = openGifContextMenu + self.loadMore = loadMore } } @@ -160,17 +169,23 @@ public final class GifPagerContentComponent: Component { 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] + 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 { @@ -186,6 +201,12 @@ public final class GifPagerContentComponent: Component { if lhs.items != rhs.items { return false } + if lhs.isLoading != rhs.isLoading { + return false + } + if lhs.loadMoreToken != rhs.loadMoreToken { + return false + } return true } @@ -256,7 +277,7 @@ public final class GifPagerContentComponent: Component { let maxVisibleRow = Int(ceil((offsetRect.maxY - self.verticalSpacing) / (self.itemSize + self.verticalSpacing))) let minVisibleIndex = minVisibleRow * self.itemsPerRow - let maxVisibleIndex = min(self.itemCount - 1, (maxVisibleRow + 1) * self.itemsPerRow - 1) + let maxVisibleIndex = (maxVisibleRow + 1) * self.itemsPerRow - 1 if maxVisibleIndex >= minVisibleIndex { return minVisibleIndex ..< (maxVisibleIndex + 1) @@ -266,11 +287,14 @@ public final class GifPagerContentComponent: Component { } } + fileprivate enum ItemKey: Hashable { + case media(MediaId) + case placeholder(Int) + } + fileprivate final class ItemLayer: GifVideoLayer { - let item: Item + let item: Item? - private let file: TelegramMediaFile - private let placeholderColor: UIColor private var disposable: Disposable? private var fetchDisposable: Disposable? @@ -282,60 +306,32 @@ public final class GifPagerContentComponent: Component { } } } - private var displayPlaceholder: Bool = false + private(set) var displayPlaceholder: Bool = false { + didSet { + if self.displayPlaceholder != oldValue { + self.onUpdateDisplayPlaceholder(self.displayPlaceholder) + } + } + } + let onUpdateDisplayPlaceholder: (Bool) -> Void init( - item: Item, + item: Item?, context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, - file: TelegramMediaFile, - placeholderColor: UIColor + onUpdateDisplayPlaceholder: @escaping (Bool) -> Void ) { self.item = item - self.file = file - self.placeholderColor = placeholderColor + self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder - super.init(context: context, file: file, synchronousLoad: attemptSynchronousLoad) + super.init(context: context, file: item?.file, synchronousLoad: attemptSynchronousLoad) self.updateDisplayPlaceholder(displayPlaceholder: true) self.started = { [weak self] in self?.updateDisplayPlaceholder(displayPlaceholder: false) } - - /*if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(groupId: groupId, target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { - self.displayPlaceholder = true - - if let image = generateStickerPlaceholderImage(data: file.immediateThumbnailData, size: self.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, 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 - } - - 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 = freeMediaFileInteractiveFetched(account: context.account, fileReference: .standalone(media: file)).start() - - return ActionDisposable { - dataDisposable.dispose() - fetchDisposable.dispose() - } - })*/ } required init?(coder: NSCoder) { @@ -364,17 +360,36 @@ public final class GifPagerContentComponent: Component { } func updateDisplayPlaceholder(displayPlaceholder: Bool) { - if self.displayPlaceholder == displayPlaceholder { - return - } - self.displayPlaceholder = displayPlaceholder + } + } + + final class ItemPlaceholderView: UIView { + private let shimmerView: PortalSourceView? + private var placeholderView: PortalView? + + init(shimmerView: PortalSourceView?) { + self.shimmerView = shimmerView + self.placeholderView = PortalView() - if displayPlaceholder { - let placeholderColor = self.placeholderColor - self.backgroundColor = placeholderColor.cgColor - } else { - self.backgroundColor = nil + 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) } } } @@ -382,9 +397,13 @@ public final class GifPagerContentComponent: Component { private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { } + private let shimmerHostView: PortalSourceView + private let standaloneShimmerEffect: StandaloneShimmerEffect + private let scrollView: ContentScrollView - private var visibleItemLayers: [MediaId: ItemLayer] = [:] + private var visibleItemPlaceholderViews: [ItemKey: ItemPlaceholderView] = [:] + private var visibleItemLayers: [ItemKey: ItemLayer] = [:] private var ignoreScrolling: Bool = false private var component: GifPagerContentComponent? @@ -392,11 +411,19 @@ public final class GifPagerContentComponent: Component { private var theme: PresentationTheme? private var itemLayout: ItemLayout? + private var currentLoadMoreToken: String? + override init(frame: CGRect) { + self.shimmerHostView = PortalSourceView() + self.standaloneShimmerEffect = StandaloneShimmerEffect() + self.scrollView = ContentScrollView() super.init(frame: frame) + 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 @@ -450,7 +477,7 @@ public final class GifPagerContentComponent: Component { @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[item.file.fileId] { + if let component = self.component, let item = self.item(atPoint: recognizer.location(in: self)), let itemView = self.visibleItemLayers[.media(item.file.fileId)] { component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemView.frame, to: self)) } } @@ -473,7 +500,11 @@ public final class GifPagerContentComponent: Component { for (_, itemLayer) in self.visibleItemLayers { if itemLayer.frame.contains(localPoint) { - return (itemLayer.item, itemLayer) + if let item = itemLayer.item { + return (item, itemLayer) + } else { + return nil + } } } @@ -497,6 +528,13 @@ public final class GifPagerContentComponent: Component { 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) { @@ -564,44 +602,104 @@ public final class GifPagerContentComponent: Component { } private func updateVisibleItems(attemptSynchronousLoads: Bool) { - guard let component = self.component, let theme = self.theme, let itemLayout = self.itemLayout else { + guard let component = self.component, let itemLayout = self.itemLayout else { return } - var validIds = Set() + var validIds = Set() if let itemRange = itemLayout.visibleItems(for: self.scrollView.bounds) { for index in itemRange.lowerBound ..< itemRange.upperBound { - let item = component.items[index] - let itemId = item.file.fileId + var item: Item? + let itemId: ItemKey + if index < component.items.count { + item = component.items[index] + itemId = .media(component.items[index].file.fileId) + } else if component.isLoading || component.loadMoreToken != nil { + itemId = .placeholder(index) + } else { + continue + } + 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, - file: item.file, - placeholderColor: theme.chat.inputMediaPanel.stickersBackgroundColor + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder 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.scrollView.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) + placeholderView.removeFromSuperview() + + strongSelf.updateShimmerIfNeeded() + } + } + } ) self.scrollView.layer.addSublayer(itemLayer) self.visibleItemLayers[itemId] = itemLayer } - itemLayer.frame = itemLayout.frame(at: index) + 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) + } + } else if updateItemLayerPlaceholder { + if itemLayer.displayPlaceholder { + itemLayer.onUpdateDisplayPlaceholder(true) + } + } } } - var removedIds: [MediaId] = [] + 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 { @@ -609,13 +707,35 @@ public final class GifPagerContentComponent: Component { } } + private func updateShimmerIfNeeded() { + if self.visibleItemPlaceholderViews.isEmpty { + self.standaloneShimmerEffect.layer = nil + } else { + self.standaloneShimmerEffect.layer = self.shimmerHostView.layer + } + } + 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 = environment[EntityKeyboardChildEnvironment.self].value.theme + 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), @@ -631,6 +751,11 @@ public final class GifPagerContentComponent: Component { 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 diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift index 4237c59b90..2a1c71affb 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift @@ -297,11 +297,11 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { var targets: [TargetReference] = [] var slotIndex: Int - private let preferredBytesPerRow: Int + private let preferredRowAlignment: Int - init(slotIndex: Int, preferredBytesPerRow: Int, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { + init(slotIndex: Int, preferredRowAlignment: Int, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable, stateUpdated: @escaping () -> Void) { self.slotIndex = slotIndex - self.preferredBytesPerRow = preferredBytesPerRow + self.preferredRowAlignment = preferredRowAlignment self.cache = cache self.stateUpdated = stateUpdated @@ -375,10 +375,10 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { let readyTextureU = texturePoolHalfPlane.take() let readyTextureV = texturePoolHalfPlane.take() let readyTextureA = texturePoolFullPlane.take() - let preferredBytesPerRow = self.preferredBytesPerRow + let preferredRowAlignment = self.preferredRowAlignment return LoadFrameTask(task: { [weak self] in - let frame = item.getFrame(at: timestamp, requestedFormat: .yuva(bytesPerRow: preferredBytesPerRow)) + let frame = item.getFrame(at: timestamp, 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) @@ -419,7 +419,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { private let texturePoolFullPlane: TextureStoragePool private let texturePoolHalfPlane: TextureStoragePool - private let preferredBytesPerRow: Int + private let preferredRowAlignment: Int private let slotCount: Int private let slotsX: Int @@ -468,7 +468,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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.preferredBytesPerRow = alignUp(size: Int(self.cellSize.width), align: TextureStorage.Content.rowAlignment(device: self.metalDevice, format: .r)) + self.preferredRowAlignment = TextureStorage.Content.rowAlignment(device: self.metalDevice, format: .r) super.init() @@ -508,7 +508,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { for i in 0 ..< self.slotCount { if self.slotToItemId[i] == nil { self.slotToItemId[i] = itemId - self.itemContexts[itemId] = ItemContext(slotIndex: i, preferredBytesPerRow: self.preferredBytesPerRow, cache: cache, itemId: itemId, size: size, fetch: fetch, stateUpdated: { [weak self] in + 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 } @@ -778,7 +778,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { self.isPlaying = isPlaying } - public func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable { + 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))) @@ -805,11 +805,11 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } } - public func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { + public func loadFirstFrameSynchronously(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool { return false } - public func loadFirstFrame(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { + public func loadFirstFrame(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { completion(false) return EmptyDisposable diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index c30fa0affe..08a52b35db 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -6,9 +6,9 @@ import AnimationCache import Accelerate public protocol MultiAnimationRenderer: AnyObject { - func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, AnimationCacheItemWriter) -> Disposable) -> Disposable - func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> Bool - func loadFirstFrame(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable + 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 @@ -60,6 +60,9 @@ open class MultiAnimationRenderTarget: SimpleLayer { open func updateDisplayPlaceholder(displayPlaceholder: Bool) { } + + open func transitionToContents(_ contents: AnyObject) { + } } private final class FrameGroup { @@ -178,8 +181,9 @@ private final class ItemAnimationContext { func updateAddedTarget(target: MultiAnimationRenderTarget) { if let currentFrameGroup = self.currentFrameGroup { - target.updateDisplayPlaceholder(displayPlaceholder: false) - target.contents = currentFrameGroup.image.cgImage + if let cgImage = currentFrameGroup.image.cgImage { + target.transitionToContents(cgImage) + } } self.updateIsPlaying() @@ -239,8 +243,7 @@ private final class ItemAnimationContext { strongSelf.currentFrameGroup = currentFrameGroup for target in strongSelf.targets.copyItems() { if let target = target.value { - target.contents = currentFrameGroup.image.cgImage - target.updateDisplayPlaceholder(displayPlaceholder: false) + target.transitionToContents(currentFrameGroup.image.cgImage!) } } } @@ -400,7 +403,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { public static let firstFrameQueue = Queue(name: "MultiAnimationRenderer-FirstFrame", qos: .userInteractive) - private var groupContexts: [String: GroupContext] = [:] + private var groupContext: GroupContext? private var frameSkip: Int private var displayLink: ConstantDisplayLinkAnimator? @@ -436,9 +439,9 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - public func add(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, fetch: @escaping (CGSize, 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(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in @@ -447,7 +450,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } strongSelf.updateIsPlaying() }) - self.groupContexts[groupId] = groupContext + self.groupContext = groupContext } let disposable = groupContext.add(target: target, cache: cache, itemId: itemId, size: size, fetch: fetch) @@ -457,9 +460,9 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } } - public func loadFirstFrameSynchronously(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize) -> 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(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in @@ -468,15 +471,15 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } strongSelf.updateIsPlaying() }) - self.groupContexts[groupId] = groupContext + self.groupContext = groupContext } return groupContext.loadFirstFrameSynchronously(target: target, cache: cache, itemId: itemId, size: size) } - public func loadFirstFrame(groupId: String, target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { + public func loadFirstFrame(target: MultiAnimationRenderTarget, cache: AnimationCache, itemId: String, size: CGSize, completion: @escaping (Bool) -> Void) -> Disposable { let groupContext: GroupContext - if let current = self.groupContexts[groupId] { + if let current = self.groupContext { groupContext = current } else { groupContext = GroupContext(firstFrameQueue: MultiAnimationRendererImpl.firstFrameQueue, stateUpdated: { [weak self] in @@ -485,7 +488,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } strongSelf.updateIsPlaying() }) - self.groupContexts[groupId] = groupContext + self.groupContext = groupContext } return groupContext.loadFirstFrame(target: target, cache: cache, itemId: itemId, size: size, completion: completion) @@ -493,10 +496,9 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { private func updateIsPlaying() { var isPlaying = false - for (_, groupContext) in self.groupContexts { + if let groupContext = self.groupContext { if groupContext.isPlaying { isPlaying = true - break } } @@ -507,7 +509,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { 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(advanceTimestamp: secondsPerFrame)) } diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index d0809698b0..e8fdca3051 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -39,6 +39,18 @@ private final class InlineStickerItem: Hashable { } } +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 @@ -105,6 +117,35 @@ public final class TextNodeWithEntities { 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) + + let itemSize = font.pointSize * 24.0 / 17.0 / CGFloat(range.length) + + let runDelegateData = RunDelegateData( + ascent: font.ascender, + descent: font.descender, + width: itemSize + ) + var callbacks = CTRunDelegateCallbacks( + version: kCTRunDelegateVersion1, + 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()) { + string.addAttribute(NSAttributedString.Key(kCTRunDelegateAttributeName as String), value: runDelegate, range: range) + } } } }) @@ -168,7 +209,7 @@ public final class TextNodeWithEntities { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: attemptSynchronousLoad, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: attemptSynchronousLoad, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) self.inlineStickerItemLayers[id] = itemLayer self.textNode.layer.addSublayer(itemLayer) @@ -331,7 +372,7 @@ public class ImmediateTextNodeWithEntities: TextNode { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, groupId: "inlineEmoji", attemptSynchronousLoad: false, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: false, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) self.inlineStickerItemLayers[id] = itemLayer self.layer.addSublayer(itemLayer) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index fae7867aee..b578b8dcf9 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1031,7 +1031,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { var insets: UIEdgeInsets var inputPanelBottomInsetTerm: CGFloat = 0.0 - if inputNodeForState != nil { + 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 { @@ -1191,9 +1196,6 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputNode.hideInputUpdated = { [weak self] transition in self?.updateInputPanelBackgroundExpansion(transition: transition) } - inputNode.expansionFractionUpdated = { [weak self] transition in - self?.updateInputPanelBackgroundExpansion(transition: transition) - } dismissedInputNode = self.inputNode if let inputNode = self.inputNode { @@ -1236,7 +1238,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { inputNodeHeightAndOverflow = ( boundedHeight, - max(0.0, inputHeight - boundedHeight) + inputNode.followsDefaultHeight ? max(0.0, inputHeight - boundedHeight) : 0.0 ) } else if let inputNode = self.inputNode { dismissedInputNode = inputNode @@ -2058,7 +2060,10 @@ 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 @@ -2171,18 +2176,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) } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 64aa27d3e5..0def32c9a9 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -238,16 +238,6 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }, chatPeerId: chatPeerId ) - let gifInputInteraction = GifPagerContentComponent.InputInteraction( - performItemAction: { [weak controllerInteraction] item, view, rect in - guard let controllerInteraction = controllerInteraction else { - return - } - let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) - }, - openGifContextMenu: { _, _, _, _, _ in - } - ) let animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { return TempBox.shared.tempFile(fileName: "file").path @@ -560,22 +550,28 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return animatedEmojiStickers } - // We are intentionally not subscribing to the recent gif updates here - let gifItems: Signal = context.engine.data.get(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) - |> map { savedGifs -> GifPagerContentComponent in - var items: [GifPagerContentComponent.Item] = [] - for gifItem in savedGifs { - items.append(GifPagerContentComponent.Item( - file: gifItem.contents.get(RecentMediaItem.self)!.media - )) + let gifInputInteraction = GifPagerContentComponent.InputInteraction( + performItemAction: { [weak controllerInteraction] item, view, rect in + guard let controllerInteraction = controllerInteraction else { + return + } + let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) + }, + openGifContextMenu: { _, _, _, _, _ in + }, + loadMore: { _ in } - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: .recent, - items: items - ) - } + ) + + // We are going to subscribe to the actual data when the view is loaded + let gifItems: Signal = .single(GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: .recent, + items: [], + isLoading: false, + loadMoreToken: nil + )) return combineLatest(queue: .mainQueue(), emojiItems, @@ -625,10 +621,195 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private var gifMode: GifPagerContentComponent.Subject = .recent { didSet { - self.gifModeSubject.set(self.gifMode) + if self.gifMode != oldValue { + self.reloadGifContext() + } } } - private let gifModeSubject: ValuePromise + + private final class GifContext { + private var componentValue: GifPagerContentComponent? { + 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 gifItems: Signal + switch subject { + case .recent: + gifItems = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) + |> map { savedGifs -> GifPagerContentComponent in + var items: [GifPagerContentComponent.Item] = [] + for gifItem in savedGifs { + items.append(GifPagerContentComponent.Item( + file: gifItem.contents.get(RecentMediaItem.self)!.media + )) + } + return GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: false, + loadMoreToken: nil + ) + } + case .trending: + gifItems = trendingGifs + |> map { trendingGifs -> GifPagerContentComponent in + var items: [GifPagerContentComponent.Item] = [] + + var isLoading = false + if let trendingGifs = trendingGifs { + for file in trendingGifs.files { + items.append(GifPagerContentComponent.Item( + file: file.file.media + )) + } + } else { + isLoading = true + } + + return GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: isLoading, + loadMoreToken: nil + ) + } + case let .emojiSearch(query): + gifItems = paneGifSearchForQuery(context: context, query: query, offset: nil, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil) + |> map { result -> GifPagerContentComponent 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.media + )) + } + loadMoreToken = result.nextOffset + } else { + isLoading = true + } + + return 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 gifItems: Signal + gifItems = paneGifSearchForQuery(context: context, query: query, offset: token, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil) + |> map { result -> GifPagerContentComponent in + var items: [GifPagerContentComponent.Item] = [] + var existingIds = Set() + for item in componentValue.items { + items.append(item) + existingIds.insert(item.file.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.media)) + } + if !result.isComplete { + loadMoreToken = result.nextOffset + } + } else { + isLoading = true + } + + return 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? init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction) { self.context = context @@ -639,17 +820,18 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.entityKeyboardView = ComponentHostView() - self.gifModeSubject = ValuePromise(self.gifMode, ignoreRepeated: true) - super.init() + self.topBackgroundExtension = 41.0 + self.followsDefaultHeight = true + self.view.addSubview(self.entityKeyboardView) self.externalTopPanelContainerImpl = PagerExternalTopPanelContainer() self.inputDataDisposable = (combineLatest(queue: .mainQueue(), updatedInputData, - self.updatedGifs() + self.gifComponent.get() ) |> deliverOnMainQueue).start(next: { [weak self] inputData, gifs in guard let strongSelf = self else { @@ -685,6 +867,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } ) + 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 { @@ -693,14 +876,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return nil } }) - } - - deinit { - self.inputDataDisposable?.dispose() - } - - private func updatedGifs() -> Signal { - let gifInputInteraction = GifPagerContentComponent.InputInteraction( + + self.gifInputInteraction = GifPagerContentComponent.InputInteraction( performItemAction: { [weak controllerInteraction] item, view, rect in guard let controllerInteraction = controllerInteraction else { return @@ -712,83 +889,26 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return } strongSelf.openGifContextMenu(file: file, 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) } ) - let context = self.context - let trendingGifs = self.trendingGifsPromise.get() - let updatedGifs = self.gifModeSubject.get() - |> mapToSignal { subject -> Signal in - switch subject { - case .recent: - let gifItems: Signal = context.engine.data.subscribe(TelegramEngine.EngineData.Item.OrderedLists.ListItems(collectionId: Namespaces.OrderedItemList.CloudRecentGifs)) - |> map { savedGifs -> GifPagerContentComponent in - var items: [GifPagerContentComponent.Item] = [] - for gifItem in savedGifs { - items.append(GifPagerContentComponent.Item( - file: gifItem.contents.get(RecentMediaItem.self)!.media - )) - } - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: subject, - items: items - ) - } - return gifItems - case .trending: - return trendingGifs - |> map { trendingGifs -> GifPagerContentComponent in - var items: [GifPagerContentComponent.Item] = [] - - if let trendingGifs = trendingGifs { - for file in trendingGifs.files { - items.append(GifPagerContentComponent.Item( - file: file.file.media - )) - } - } - - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: subject, - items: items - ) - } - case let .emojiSearch(query): - return paneGifSearchForQuery(context: context, query: query, offset: nil, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil) - |> map { result -> GifPagerContentComponent in - var items: [GifPagerContentComponent.Item] = [] - - /*let canLoadMore: Bool - if let result = result { - canLoadMore = !result.isComplete - } else { - canLoadMore = true - }*/ - - if let result = result { - for file in result.files { - items.append(GifPagerContentComponent.Item( - file: file.file.media - )) - } - } - - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: subject, - items: items - ) - } - } + self.reloadGifContext() + } + + deinit { + self.inputDataDisposable?.dispose() + } + + private func reloadGifContext() { + if let gifInputInteraction = self.gifInputInteraction { + self.gifContext = GifContext(context: self.context, subject: self.gifMode, gifInputInteraction: gifInputInteraction, trendingGifs: self.trendingGifsPromise.get()) } - - return .single(self.currentInputData.gifs) - |> then(updatedGifs) } func markInputCollapsed() { @@ -808,7 +928,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let wasMarkedInputCollapsed = self.isMarkInputCollapsed self.isMarkInputCollapsed = false - let expandedHeight = standardInputHeight + self.expansionFraction * (maximumHeight - standardInputHeight) + let expandedHeight = standardInputHeight var hiddenInputHeight: CGFloat = 0.0 if self.hideInput && !self.adjustLayoutForHiddenInput { @@ -822,18 +942,37 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var mappedTransition = Transition(transition) - if wasMarkedInputCollapsed { + if wasMarkedInputCollapsed || !isExpanded { mappedTransition = mappedTransition.withUserData(EntityKeyboardComponent.MarkInputCollapsed()) } + var stickerContent: EmojiPagerContentComponent? = self.currentInputData.stickers + var gifContent: GifPagerContentComponent? = 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 + } + let entityKeyboardSize = self.entityKeyboardView.update( transition: mappedTransition, component: AnyComponent(EntityKeyboardComponent( theme: interfaceState.theme, bottomInset: bottomInset, emojiContent: self.currentInputData.emoji, - stickerContent: self.currentInputData.stickers, - gifContent: self.currentInputData.gifs, + stickerContent: stickerContent, + gifContent: gifContent, availableGifSearchEmojies: self.currentInputData.availableGifSearchEmojies, defaultToEmojiTab: self.defaultToEmojiTab, externalTopPanelContainer: self.externalTopPanelContainerImpl, @@ -868,7 +1007,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let strongSelf = self else { return } - strongSelf.gifModeSubject.set(subject) + strongSelf.gifMode = subject }, makeSearchContainerNode: { content in let mappedMode: ChatMediaInputSearchMode diff --git a/submodules/TelegramUI/Sources/ChatInputNode.swift b/submodules/TelegramUI/Sources/ChatInputNode.swift index 311f6a0a8d..1aa38814f0 100644 --- a/submodules/TelegramUI/Sources/ChatInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatInputNode.swift @@ -15,15 +15,14 @@ class ChatInputNode: ASDisplayNode { return nil } - var topBackgroundExtension: CGFloat = 41.0 + var topBackgroundExtension: CGFloat = 0.0 var topBackgroundExtensionUpdated: ((ContainedViewLayoutTransition) -> Void)? var hideInput: Bool = false var adjustLayoutForHiddenInput: Bool = false var hideInputUpdated: ((ContainedViewLayoutTransition) -> Void)? - var expansionFraction: CGFloat = 0.0 - var expansionFractionUpdated: ((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/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index 3e8289094b..7c88fd6fb8 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift @@ -272,15 +272,8 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte case .inputButtons: return ChatTextInputPanelState(accessoryItems: [.keyboard], contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) case .none, .text: - if let editMessage = chatPresentationInterfaceState.interfaceState.editMessage { - let isTextEmpty = editMessage.inputState.inputText.length == 0 - - let stickersAreEmoji = !isTextEmpty - - var stickersEnabled = true - stickersEnabled = true - - accessoryItems.append(.stickers(isEnabled: stickersEnabled, isEmoji: stickersAreEmoji)) + if let _ = chatPresentationInterfaceState.interfaceState.editMessage { + accessoryItems.append(.stickers(isEnabled: true, isEmoji: true)) return ChatTextInputPanelState(accessoryItems: accessoryItems, contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) } else { @@ -330,7 +323,11 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte accessoryItems.append(.commands) } - accessoryItems.append(.stickers(isEnabled: stickersEnabled, isEmoji: stickersAreEmoji)) + if stickersEnabled { + accessoryItems.append(.stickers(isEnabled: true, isEmoji: stickersAreEmoji)) + } else { + accessoryItems.append(.stickers(isEnabled: true, isEmoji: true)) + } if isTextEmpty, let message = chatPresentationInterfaceState.keyboardButtonsMessage, let _ = message.visibleButtonKeyboardMarkup, chatPresentationInterfaceState.interfaceState.messageActionsState.dismissedButtonKeyboardMessageId != message.id { accessoryItems.append(.inputButtons) diff --git a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift index 6d1a5550fe..2df9ca3c88 100644 --- a/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageTextBubbleContentNode.swift @@ -49,7 +49,7 @@ private final class CachedChatMessageText { class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { private let textNode: TextNodeWithEntities - private var spoilerTextNode: TextNode? + private var spoilerTextNode: TextNodeWithEntities? private var dustNode: InvisibleInkDustNode? private let textAccessibilityOverlayNode: TextAccessibilityOverlayNode @@ -67,11 +67,13 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { 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 } } } @@ -120,7 +122,7 @@ 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 = TextNodeWithEntities.asyncLayout(self.textNode) - let spoilerTextLayout = TextNode.asyncLayout(self.spoilerTextNode) + let spoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode) let statusLayout = self.statusNode.asyncLayout() let currentCachedChatMessageText = self.cachedChatMessageText @@ -339,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 } @@ -440,33 +442,33 @@ class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode { 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 @@ -474,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 diff --git a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift index cfb4bb135a..c07d3aa24c 100644 --- a/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatPinnedMessageTitlePanelNode.swift @@ -56,7 +56,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { private let lineNode: AnimatedNavigationStripeNode private let titleNode: AnimatedCountLabelNode private let textNode: TextNodeWithEntities - private var spoilerTextNode: TextNode? + private var spoilerTextNode: TextNodeWithEntities? private var dustNode: InvisibleInkDustNode? private let actionButton: HighlightableButtonNode private let actionButtonTitleNode: ImmediateTextNode @@ -525,7 +525,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { let makeTitleLayout = self.titleNode.asyncLayout() let makeTextLayout = TextNodeWithEntities.asyncLayout(self.textNode) - let makeSpoilerTextLayout = TextNode.asyncLayout(self.spoilerTextNode) + let makeSpoilerTextLayout = TextNodeWithEntities.asyncLayout(self.spoilerTextNode) let imageNodeLayout = self.imageNode.asyncLayout() let previousMediaReference = self.previousMediaReference @@ -668,9 +668,9 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { 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 } @@ -701,33 +701,33 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode { 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.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 @@ -735,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/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index f7de318cab..4dde3ce13c 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -619,10 +619,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() @@ -1782,6 +1785,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) @@ -2069,7 +2073,9 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { let endIndex = currentIndex addSpoiler(startIndex: currentStartIndex, endIndex: endIndex) } - } else if let value = attributes[ChatTextInputAttributes.customEmoji] as? ChatTextInputTextCustomEmojiAttribute { + } + + 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 { diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index 57ddcbac1b..73927f1538 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -126,11 +126,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/TextFormat/Sources/ChatTextInputAttributes.swift b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift index 8d3924042d..6d81e65b0c 100644 --- a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift +++ b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift @@ -139,35 +139,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 } @@ -562,15 +533,6 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme } } else if key == ChatTextInputAttributes.customEmoji, let value = value as? ChatTextInputTextCustomEmojiAttribute { textNode.textView.textStorage.addAttribute(key, value: value, range: range) - if let emojiViewProvider = emojiViewProvider { - let _ = emojiViewProvider - /*let emojiText = attributedText.attributedSubstring(from: range) - let attachment = EmojiTextAttachment(index: emojiIndex, text: emojiText.string, emoji: value, viewProvider: emojiViewProvider) - emojiIndex += 1 - attachment.bounds = CGRect(origin: CGPoint(), size: CGSize(width: 26.0, height: 16.0)) - - replaceRanges.append((range, attachment))*/ - } } } @@ -602,52 +564,6 @@ public func refreshChatTextInputAttributes(_ textNode: ASEditableTextNode, theme textNode.textView.textStorage.replaceCharacters(in: range, with: NSAttributedString(attachment: attachment)) } } - - if #available(iOS 15, *), let _ = 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 < 400 { - 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 - } - }*/ - } } public func refreshGenericTextInputAttributes(_ textNode: ASEditableTextNode, theme: PresentationTheme, baseFontSize: CGFloat, availableEmojis: Set, emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)?, spoilersRevealed: Bool = false) { From eaf0b74f1ba6d2412eb1b61a75af6466f1197dbd Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 15 Jul 2022 14:49:48 +0200 Subject: [PATCH 055/113] Emoji input and display in media selection --- submodules/AttachmentTextInputPanelNode/BUILD | 5 + .../AttachmentTextInputPanelNode.swift | 332 +++++++++++-- .../Sources/AttachmentController.swift | 13 +- .../Sources/AttachmentPanel.swift | 8 +- .../Sources/PagerComponent.swift | 6 +- submodules/GalleryUI/BUILD | 3 + .../ChatItemGalleryFooterContentNode.swift | 28 +- .../Sources/EntityKeyboard.swift | 7 +- .../EntityKeyboardBottomPanelComponent.swift | 95 ++-- ...tyKeyboardTopContainerPanelComponent.swift | 45 +- .../EntitySearchContentComponent.swift | 42 +- .../Sources/TextNodeWithEntities.swift | 2 +- .../TelegramUI/Sources/ChatController.swift | 15 +- .../Sources/ChatControllerNode.swift | 3 +- .../Sources/ChatEntityKeyboardInputNode.swift | 466 +++++++++++++----- .../Sources/PeerSelectionControllerNode.swift | 4 +- .../Sources/ReplyAccessoryPanelNode.swift | 1 + .../WebUI/Sources/WebAppController.swift | 4 +- 18 files changed, 829 insertions(+), 250 deletions(-) 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 d747d0be7d..f39df3f87a 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)? @@ -108,33 +113,6 @@ private func textInputBackgroundImage(backgroundColor: UIColor?, inputBackground } } -private final class EntityInputView: UIInputView, UIInputViewAudioFeedback { - override var inputViewStyle: UIInputView.Style { - get { - return .default - } - } - override var allowsSelfSizing: Bool { - get { - return true - } - set { - } - } - - override var intrinsicContentSize: CGSize { - CGSize(width: UIView.noIntrinsicMetric, height: 300) - } - - override func sizeToFit() { - print("sizeToFit") - } - - override func sizeThatFits(_ size: CGSize) -> CGSize { - return CGSize(width: size.width, height: 100.0) - } -} - private class CaptionEditableTextNode: EditableTextNode { override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { let previousAlpha = self.alpha @@ -145,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 @@ -164,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)? @@ -270,14 +323,23 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS private var spoilersRevealed = false private 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 { @@ -293,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() @@ -303,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() @@ -331,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 @@ -343,13 +407,13 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS } 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)) + } self.updateSendButtonEnabled(isCaption || isAttachment, animated: false) @@ -464,11 +528,6 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS textInputNode.view.addGestureRecognizer(recognizer) textInputNode.textView.accessibilityHint = self.textPlaceholderNode.attributedText?.string - - /*let entityInputView = EntityInputView() - entityInputView.frame = CGRect(origin: CGPoint(), size: CGSize(width: 100.0, height: 100.0)) - entityInputView.backgroundColor = .blue - textInputNode.textView.inputView = entityInputView*/ } private func textFieldMaxHeight(_ maxHeight: CGFloat, metrics: LayoutMetrics) -> CGFloat { @@ -528,6 +587,14 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS return minimalHeight } + 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 @@ -688,7 +755,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 @@ -698,7 +765,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) } @@ -711,9 +778,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() } @@ -725,6 +817,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() @@ -788,6 +883,37 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS var textInputViewRealInsets = UIEdgeInsets() if let presentationInterfaceState = self.presentationInterfaceState { textInputViewRealInsets = calculateTextFieldRealInsets(presentationInterfaceState) + + var colors: [String: UIColor] = [:] + let colorKeys: [String] = [ + "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" + ] + for colorKey in colorKeys { + colors[colorKey] = presentationInterfaceState.theme.chat.inputPanel.inputControlColor + } + let animationComponent = LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: "anim_smiletosticker", + colors: colors, + mode: .animateTransitionFromPrevious + ), + 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 @@ -836,6 +962,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 @@ -873,6 +1000,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 + } + } + } }) } @@ -893,6 +1030,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) { @@ -1016,6 +1175,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 { @@ -1037,12 +1261,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) @@ -1052,15 +1276,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 diff --git a/submodules/AttachmentUI/Sources/AttachmentController.swift b/submodules/AttachmentUI/Sources/AttachmentController.swift index e8bfdf2ad8..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 @@ -167,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 = {} @@ -190,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? @@ -259,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 @@ -274,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 @@ -843,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) @@ -877,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 547c91d193..996242b0a7 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) @@ -895,7 +899,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 { diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index b14ec8d808..b3b0ce76ce 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -543,7 +543,11 @@ public final class PagerComponent Void public let switchToTextInput: () -> Void public let switchToGifSubject: (GifPagerContentComponent.Subject) -> Void - public let makeSearchContainerNode: (EntitySearchContentType) -> EntitySearchContainerNode + public let makeSearchContainerNode: (EntitySearchContentType) -> EntitySearchContainerNode? public let deviceMetrics: DeviceMetrics public let hiddenInputHeight: CGFloat public let isExpanded: Bool @@ -103,7 +103,7 @@ public final class EntityKeyboardComponent: Component { hideInputUpdated: @escaping (Bool, Bool, Transition) -> Void, switchToTextInput: @escaping () -> Void, switchToGifSubject: @escaping (GifPagerContentComponent.Subject) -> Void, - makeSearchContainerNode: @escaping (EntitySearchContentType) -> EntitySearchContainerNode, + makeSearchContainerNode: @escaping (EntitySearchContentType) -> EntitySearchContainerNode?, deviceMetrics: DeviceMetrics, hiddenInputHeight: CGFloat, isExpanded: Bool @@ -486,7 +486,8 @@ public final class EntityKeyboardComponent: Component { )), topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent( theme: component.theme, - overflowHeight: component.hiddenInputHeight + overflowHeight: component.hiddenInputHeight, + displayBackground: component.externalTopPanelContainer == nil )), externalTopPanelContainer: component.externalTopPanelContainer, bottomPanel: AnyComponent(EntityKeyboardBottomPanelComponent( diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift index 495748e37b..a1925f41d8 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift @@ -278,59 +278,64 @@ final class EntityKeyboardBottomPanelComponent: Component { let navigateToContentId = panelEnvironment.navigateToContentId - 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) + 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( + content: icon.component, + action: { + navigateToContentId(icon.id) + } + )), + environment: {}, + containerSize: CGSize(width: 32.0, height: 32.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) } - - let iconSize = iconView.update( - transition: iconTransition, - component: AnyComponent(BottomPanelIconComponent( - content: icon.component, - action: { - navigateToContentId(icon.id) - } - )), - environment: {}, - containerSize: CGSize(width: 32.0, height: 32.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.bottomInset > 0.0 { nextIconOrigin.y += 2.0 } - for icon in panelEnvironment.contentIcons { - guard let iconInfo = iconInfos[icon.id], let iconView = self.iconViews[icon.id] else { - continue + + 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) + } + + nextIconOrigin.x += iconInfo.size.width + iconSpacing } - - 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) - } - - nextIconOrigin.x += iconInfo.size.width + iconSpacing } if activeContentId == nil { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift index ba093de32b..54bacc37aa 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -32,13 +32,16 @@ final class EntityKeyboardTopContainerPanelComponent: Component { let theme: PresentationTheme let overflowHeight: CGFloat + let displayBackground: Bool init( theme: PresentationTheme, - overflowHeight: CGFloat + overflowHeight: CGFloat, + displayBackground: Bool ) { self.theme = theme self.overflowHeight = overflowHeight + self.displayBackground = displayBackground } static func ==(lhs: EntityKeyboardTopContainerPanelComponent, rhs: EntityKeyboardTopContainerPanelComponent) -> Bool { @@ -48,6 +51,9 @@ final class EntityKeyboardTopContainerPanelComponent: Component { if lhs.overflowHeight != rhs.overflowHeight { return false } + if lhs.displayBackground != rhs.displayBackground { + return false + } return true } @@ -59,6 +65,9 @@ final class EntityKeyboardTopContainerPanelComponent: Component { } final class View: UIView { + private var backgroundView: BlurredBackgroundView? + private var backgroundSeparatorView: UIView? + private var panelViews: [AnyHashable: PanelView] = [:] private var component: EntityKeyboardTopContainerPanelComponent? @@ -183,6 +192,40 @@ final class EntityKeyboardTopContainerPanelComponent: Component { 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) } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift index a6febf912f..6424d92c18 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntitySearchContentComponent.swift @@ -51,11 +51,11 @@ final class EntitySearchContentEnvironment: Equatable { final class EntitySearchContentComponent: Component { typealias EnvironmentType = EntitySearchContentEnvironment - let makeContainerNode: () -> EntitySearchContainerNode + let makeContainerNode: () -> EntitySearchContainerNode? let dismissSearch: () -> Void init( - makeContainerNode: @escaping () -> EntitySearchContainerNode, + makeContainerNode: @escaping () -> EntitySearchContainerNode?, dismissSearch: @escaping () -> Void ) { self.makeContainerNode = makeContainerNode @@ -78,30 +78,34 @@ final class EntitySearchContentComponent: Component { } func update(component: EntitySearchContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { - let containerNode: EntitySearchContainerNode + let containerNode: EntitySearchContainerNode? if let current = self.containerNode { containerNode = current } else { containerNode = component.makeContainerNode() - self.containerNode = containerNode - self.addSubnode(containerNode) + 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() + 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 diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index e8fdca3051..1b58dcbb53 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -118,7 +118,7 @@ public final class TextNodeWithEntities { 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) - let itemSize = font.pointSize * 24.0 / 17.0 / CGFloat(range.length) + let itemSize = font.pointSize * 24.0 / 17.0 / CGFloat(min(2, range.length)) let runDelegateData = RunDelegateData( ascent: font.ascender, diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 26fab2afb2..917b839354 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -10732,7 +10732,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) + }) inputPanelNode.interfaceInteraction = interfaceInteraction inputPanelNode.effectivePresentationInterfaceState = { return presentationInterfaceState @@ -10967,7 +10973,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) + }) attachmentController.requestController = { [weak self, weak attachmentController] type, completion in guard let strongSelf = self else { return diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index b578b8dcf9..0e1186d180 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -540,14 +540,13 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { } self.addSubnode(self.inputPanelContainerNode) + self.addSubnode(self.inputContextPanelContainer) self.inputPanelContainerNode.addSubnode(self.inputPanelClippingNode) self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundNode) self.inputPanelClippingNode.addSubnode(self.inputPanelBackgroundSeparatorNode) self.inputPanelBackgroundNode.addSubnode(self.inputPanelBottomBackgroundSeparatorNode) - self.contentContainerNode.addSubnode(self.inputContextPanelContainer) - self.addSubnode(self.messageTransitionNode) self.contentContainerNode.addSubnode(self.navigateButtons) self.contentContainerNode.addSubnode(self.presentationContextMarker) diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 0def32c9a9..22b3258fb6 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -21,6 +21,8 @@ import AudioToolbox import UndoUI import ContextUI import GalleryUI +import AttachmentTextInputPanelNode +import TelegramPresentationData private let staticEmojiMapping: [(EmojiPagerContentComponent.StaticEmojiSegment, [String])] = { guard let path = getAppBundle().path(forResource: "emoji1016", ofType: "txt") else { @@ -46,14 +48,14 @@ private let staticEmojiMapping: [(EmojiPagerContentComponent.StaticEmojiSegment, final class ChatEntityKeyboardInputNode: ChatInputNode { struct InputData: Equatable { var emoji: EmojiPagerContentComponent - var stickers: EmojiPagerContentComponent - var gifs: GifPagerContentComponent + var stickers: EmojiPagerContentComponent? + var gifs: GifPagerContentComponent? var availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] init( emoji: EmojiPagerContentComponent, - stickers: EmojiPagerContentComponent, - gifs: GifPagerContentComponent, + stickers: EmojiPagerContentComponent?, + gifs: GifPagerContentComponent?, availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] ) { self.emoji = emoji @@ -63,7 +65,109 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - static func inputData(context: AccountContext, interfaceInteraction: ChatPanelInterfaceInteraction, controllerInteraction: ChatControllerInteraction, chatPeerId: PeerId?) -> Signal { + static func emojiInputData(context: AccountContext, inputInteraction: EmojiPagerContentComponent.InputInteraction, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer) -> 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 emojiItems: Signal = combineLatest( + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + hasPremium + ) + |> map { view, hasPremium -> EmojiPagerContentComponent in + struct ItemGroup { + var supergroupId: AnyHashable + var id: AnyHashable + var isPremium: Bool + var items: [EmojiPagerContentComponent.Item] + } + var itemGroups: [ItemGroup] = [] + var itemGroupIndexById: [AnyHashable: Int] = [:] + + 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, isPremium: 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 supergroupId = entry.index.collectionId + let groupId: AnyHashable = supergroupId + let isPremium: Bool = item.file.isPremiumEmoji && !hasPremium + if isPremium && isPremiumDisabled { + continue + } + /*if isPremium { + groupId = "\(supergroupId)-p" + } else { + groupId = supergroupId + }*/ + if let groupIndex = itemGroupIndexById[groupId] { + itemGroups[groupIndex].items.append(resultItem) + } else { + itemGroupIndexById[groupId] = itemGroups.count + itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, isPremium: isPremium, items: [resultItem])) + } + } + + return EmojiPagerContentComponent( + id: "emoji", + context: context, + animationCache: animationCache, + animationRenderer: animationRenderer, + inputInteraction: inputInteraction, + itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in + var title: String? + if group.id == AnyHashable("recent") { + //TODO:localize + title = "Recently Used" + } else { + for (id, info, _) in view.collectionInfos { + if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { + title = info.title + break + } + } + } + + return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: title, isPremium: group.isPremium, 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 @@ -177,9 +281,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { chatPeerId: chatPeerId ) let stickerInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak interfaceInteraction] item, view, rect, layer in + performItemAction: { [weak controllerInteraction, weak interfaceInteraction] item, view, rect, layer in let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in - guard let interfaceInteraction = interfaceInteraction else { + guard let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { return } if let file = item.file { @@ -249,98 +353,13 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { animationRenderer = MultiAnimationRendererImpl() //} - let orderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] - let namespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] + let emojiItems = emojiInputData(context: context, inputInteraction: emojiInputInteraction, animationCache: animationCache, animationRenderer: animationRenderer) - let emojiItems: Signal = combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), - hasPremium - ) - |> map { view, hasPremium -> EmojiPagerContentComponent in - struct ItemGroup { - var supergroupId: AnyHashable - var id: AnyHashable - var isPremium: Bool - var items: [EmojiPagerContentComponent.Item] - } - var itemGroups: [ItemGroup] = [] - var itemGroupIndexById: [AnyHashable: Int] = [:] - - 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, isPremium: 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 supergroupId = entry.index.collectionId - let groupId: AnyHashable = supergroupId - let isPremium: Bool = item.file.isPremiumEmoji && !hasPremium - if isPremium && isPremiumDisabled { - continue - } - /*if isPremium { - groupId = "\(supergroupId)-p" - } else { - groupId = supergroupId - }*/ - if let groupIndex = itemGroupIndexById[groupId] { - itemGroups[groupIndex].items.append(resultItem) - } else { - itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, isPremium: isPremium, items: [resultItem])) - } - } - - return EmojiPagerContentComponent( - id: "emoji", - context: context, - animationCache: animationCache, - animationRenderer: animationRenderer, - inputInteraction: emojiInputInteraction, - itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in - var title: String? - if group.id == AnyHashable("recent") { - //TODO:localize - title = "Recently Used" - } else { - for (id, info, _) in view.collectionInfos { - if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { - title = info.title - break - } - } - } - - return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: title, isPremium: group.isPremium, displayPremiumBadges: false, items: group.items) - }, - itemLayoutType: .compact - ) - } + let stickerNamespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] + let stickerOrderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] let stickerItems: Signal = combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: orderedItemListCollectionIds, namespaces: namespaces, aroundIndex: nil, count: 10000000), + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: stickerOrderedItemListCollectionIds, namespaces: stickerNamespaces, aroundIndex: nil, count: 10000000), hasPremium ) |> map { view, hasPremium -> EmojiPagerContentComponent in @@ -604,7 +623,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private var currentInputData: InputData private var inputDataDisposable: Disposable? - private let controllerInteraction: ChatControllerInteraction + private let controllerInteraction: ChatControllerInteraction? private var inputNodeInteraction: ChatMediaInputNodeInteraction? @@ -617,6 +636,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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 gifMode: GifPagerContentComponent.Subject = .recent { @@ -811,7 +832,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private let gifComponent = Promise() private var gifInputInteraction: GifPagerContentComponent.InputInteraction? - init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction) { + init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction?) { self.context = context self.currentInputData = currentInputData self.defaultToEmojiTab = defaultToEmojiTab @@ -898,6 +919,15 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } ) + self.switchToTextInput = { [weak self] in + guard let strongSelf = self, let controllerInteraction = strongSelf.controllerInteraction else { + return + } + controllerInteraction.updateInputMode { _ in + return .text + } + } + self.reloadGifContext() } @@ -996,12 +1026,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } }, switchToTextInput: { [weak self] in - guard let strongSelf = self else { - return - } - strongSelf.controllerInteraction.updateInputMode { _ in - return .text - } + self?.switchToTextInput?() }, switchToGifSubject: { [weak self] subject in guard let strongSelf = self else { @@ -1009,7 +1034,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } strongSelf.gifMode = subject }, - makeSearchContainerNode: { content in + makeSearchContainerNode: { [weak controllerInteraction] content in + guard let controllerInteraction = controllerInteraction else { + return nil + } + let mappedMode: ChatMediaInputSearchMode switch content { case .stickers: @@ -1074,7 +1103,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }, action: { _, f in f(.default) if isSaved { - let _ = self?.controllerInteraction.sendGif(FileMediaReference.savedGif(media: file), sourceView, sourceRect, false, false) + 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) }*/ @@ -1141,7 +1170,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { |> 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) + 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 @@ -1150,10 +1179,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } 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 + 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) + controllerInteraction?.navigationController()?.pushViewController(controller) return true } return false @@ -1164,7 +1193,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } 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) + strongSelf.controllerInteraction?.presentGlobalOverlayController(contextController, nil) }) } } @@ -1202,3 +1231,220 @@ private final class ContextControllerContentSourceImpl: ContextControllerContent } } } + +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 + ) { + 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 { + //TODO:localize + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + strongSelf.presentController?(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { + guard let strongSelf = self else { + return + } + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: strongSelf.context, subject: .premiumStickers, action: { + let controller = PremiumIntroScreen(context: strongSelf.context, source: .stickers) + 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: { + }, + openPremiumSection: { + }, + 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, inputInteraction: inputInteraction, animationCache: self.animationCache, animationRenderer: self.animationRenderer).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 + ) + self.inputNode = inputNode + 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/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index a99acd9b86..6693d99a67 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -390,7 +390,9 @@ final class PeerSelectionControllerNode: ASDisplayNode { 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 { diff --git a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift index a80f41176a..4469e3bf1a 100644 --- a/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift +++ b/submodules/TelegramUI/Sources/ReplyAccessoryPanelNode.swift @@ -70,6 +70,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode { 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( diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index f51919647f..716b0ef356 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -1212,7 +1212,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) From 89ecb672c7b9c94dbd838a35425aa5d259815e9d Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 15 Jul 2022 16:05:37 +0200 Subject: [PATCH 056/113] Animated emoji autocompletion --- .../Sources/ChatController.swift | 10 +- .../AttachmentTextInputPanelNode.swift | 2 +- .../Sources/EmojiTextAttachmentView.swift | 4 +- .../Sources/EmojiPagerContentComponent.swift | 14 +-- .../Sources/ChatControllerNode.swift | 4 +- .../Sources/ChatInputContextPanelNode.swift | 2 +- .../ChatInterfaceInputContextPanels.swift | 24 ++-- .../ChatInterfaceStateContextQueries.swift | 64 ++++++++-- .../Sources/ChatTextInputPanelNode.swift | 2 +- .../CommandChatInputContextPanelNode.swift | 4 +- ...CommandMenuChatInputContextPanelNode.swift | 4 +- ...textResultsChatInputContextPanelNode.swift | 4 +- .../EmojisChatInputContextPanelNode.swift | 110 ++++++++++++------ .../Sources/EmojisChatInputPanelItem.swift | 59 +++++++++- .../HashtagChatInputContextPanelNode.swift | 4 +- ...textResultsChatInputContextPanelNode.swift | 4 +- ...rizontalStickersChatContextPanelNode.swift | 4 +- .../Sources/InlineReactionSearchPanel.swift | 4 +- .../MentionChatInputContextPanelNode.swift | 4 +- .../StickersChatInputContextPanelNode.swift | 4 +- ...textResultsChatInputContextPanelNode.swift | 4 +- 21 files changed, 235 insertions(+), 100 deletions(-) diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index c7df317a73..e0856e484f 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -469,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 { @@ -513,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 } } diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index f39df3f87a..9d4a7ec421 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -412,7 +412,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS return UIView() } - return EmojiTextAttachmentView(context: context, emoji: emoji, file: emoji.file, cache: strongSelf.animationCache, renderer: strongSelf.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12)) + 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) diff --git a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift index 2e0f126b61..4915147929 100644 --- a/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift +++ b/submodules/TelegramUI/Components/EmojiTextAttachmentView/Sources/EmojiTextAttachmentView.swift @@ -249,8 +249,8 @@ public final class InlineStickerItemLayer: MultiAnimationRenderTarget { public final class EmojiTextAttachmentView: UIView { private let contentLayer: InlineStickerItemLayer - public init(context: AccountContext, emoji: ChatTextInputTextCustomEmojiAttribute, file: TelegramMediaFile?, cache: AnimationCache, renderer: MultiAnimationRenderer, placeholderColor: UIColor) { - self.contentLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: true, emoji: emoji, file: file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: 24.0, height: 24.0)) + 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()) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 903aa9d4d6..be5edb1358 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -350,7 +350,7 @@ public final class EmojiPagerContentComponent: Component { var premiumButtonInset: CGFloat var premiumButtonHeight: CGFloat - init(width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], itemLayoutType: ItemLayoutType, expandedPremiumGroups: Set) { + init(width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], itemLayoutType: ItemLayoutType) { self.width = width self.containerInsets = containerInsets @@ -392,7 +392,7 @@ public final class EmojiPagerContentComponent: Component { let numRowsInGroup = (itemGroup.itemCount + (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.isPremium && expandedPremiumGroups.contains(itemGroup.groupId) { + if itemGroup.isPremium { groupContentSize.height += self.premiumButtonInset + self.premiumButtonHeight } self.itemGroupLayouts.append(ItemGroupLayout( @@ -765,7 +765,6 @@ public final class EmojiPagerContentComponent: Component { private var visibleGroupHeaders: [AnyHashable: GroupHeaderLayer] = [:] private var visibleGroupBorders: [AnyHashable: GroupBorderLayer] = [:] private var visibleGroupPremiumButtons: [AnyHashable: ComponentView] = [:] - private var expandedPremiumGroups: Set = Set() private var ignoreScrolling: Bool = false private var keepTopPanelVisibleUntilScrollingInput: Bool = false @@ -1034,7 +1033,8 @@ public final class EmojiPagerContentComponent: Component { 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) { - for group in component.itemGroups { + let _ = id + /*for group in component.itemGroups { if group.groupId == id { if group.isPremium && !self.expandedPremiumGroups.contains(id) { if self.expandedPremiumGroups.contains(id) { @@ -1059,7 +1059,7 @@ public final class EmojiPagerContentComponent: Component { break outer } } - } + }*/ } } @@ -1288,7 +1288,7 @@ public final class EmojiPagerContentComponent: Component { } groupBorderTransition.setFrame(layer: groupBorderLayer, frame: groupBorderFrame) - if self.expandedPremiumGroups.contains(itemGroup.groupId) { + if itemGroup.isPremium { validGroupPremiumButtonIds.insert(itemGroup.groupId) let groupPremiumButton: ComponentView @@ -1562,7 +1562,7 @@ public final class EmojiPagerContentComponent: Component { var itemTransition = transition - let itemLayout = ItemLayout(width: availableSize.width, containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top + 9.0, left: pagerEnvironment.containerInsets.left + 12.0, bottom: 9.0 + pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right + 12.0), itemGroups: itemGroups, itemLayoutType: component.itemLayoutType, expandedPremiumGroups: expandedPremiumGroups) + let itemLayout = ItemLayout(width: availableSize.width, containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top + 9.0, left: pagerEnvironment.containerInsets.left + 12.0, bottom: 9.0 + pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right + 12.0), itemGroups: itemGroups, itemLayoutType: component.itemLayoutType) if let previousItemLayout = self.itemLayout { if previousItemLayout.width != itemLayout.width { itemTransition = .immediate diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 0e1186d180..016c32deda 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1331,7 +1331,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { let (duration, curve) = listViewAnimationDurationAndCurve(transition: transition) 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 @@ -1345,7 +1345,7 @@ 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 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/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/ChatInterfaceStateContextQueries.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift index 6a5ce76378..b4dc54ec9c 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift @@ -341,21 +341,61 @@ 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] { + 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/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 4dde3ce13c..692d82c6a2 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -802,7 +802,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { return UIView() } - return EmojiTextAttachmentView(context: context, emoji: emoji, file: emoji.file, cache: presentationContext.animationCache, renderer: presentationContext.animationRenderer, placeholderColor: presentationInterfaceState.theme.chat.inputPanel.inputTextColor.withAlphaComponent(0.12)) + 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: 24.0, height: 24.0)) } } } 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/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/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/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 c66d66445e..5b11f04846 100644 --- a/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalListContextResultsChatInputContextPanelNode.swift @@ -91,7 +91,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 +108,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 diff --git a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift index f9edf19c44..bb628b32cc 100755 --- a/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/HorizontalStickersChatContextPanelNode.swift @@ -117,7 +117,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 +144,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 diff --git a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift index c9a9869dd1..1b42e1de09 100644 --- a/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift +++ b/submodules/TelegramUI/Sources/InlineReactionSearchPanel.swift @@ -492,7 +492,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 +535,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 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/StickersChatInputContextPanelNode.swift b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift index eb919dbc49..b911eef5be 100644 --- a/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift +++ b/submodules/TelegramUI/Sources/StickersChatInputContextPanelNode.swift @@ -84,7 +84,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 +99,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 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 From 2a5b45883dfe0a8cfc0d18df8ce21c76694fc888 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 16 Jul 2022 02:02:39 +0200 Subject: [PATCH 057/113] Emoji fixes --- .../Pasteboard/Sources/Pasteboard.swift | 29 +++++--- .../Sources/GifPagerContentComponent.swift | 67 +++++++++++++------ .../Sources/TextNodeWithEntities.swift | 35 +++++++--- .../Sources/ChatTextInputAttributes.swift | 5 +- submodules/TextSelectionNode/BUILD | 1 + .../Sources/TextSelectionNode.swift | 34 ++++++++-- 6 files changed, 126 insertions(+), 45 deletions(-) diff --git a/submodules/Pasteboard/Sources/Pasteboard.swift b/submodules/Pasteboard/Sources/Pasteboard.swift index fa4f09165b..b25ab49f55 100644 --- a/submodules/Pasteboard/Sources/Pasteboard.swift +++ b/submodules/Pasteboard/Sources/Pasteboard.swift @@ -9,13 +9,14 @@ private func rtfStringWithAppliedEntities(_ text: String, entities: [MessageText 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) - if #available(iOS 15.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?\(value.fileId)")!, range: range) - } - }) - } + 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) { @@ -71,10 +72,18 @@ public func chatInputStateStringFromRTF(_ data: Data, type: NSAttributedString.D if let attributedString = try? NSAttributedString(data: data, options: [NSAttributedString.DocumentReadingOptionKey.documentType: type], documentAttributes: nil) { 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", let query = url.query { - if let fileId = Int64(query) { + 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: fileId, file: nil), range: range) + updatedString.addAttribute(ChatTextInputAttributes.customEmoji, value: ChatTextInputTextCustomEmojiAttribute(stickerPack: nil, fileId: emojiId, file: nil), range: range) } } }) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index a31a717d95..d0caa97fcf 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -306,31 +306,28 @@ public final class GifPagerContentComponent: Component { } } } - private(set) var displayPlaceholder: Bool = false { - didSet { - if self.displayPlaceholder != oldValue { - self.onUpdateDisplayPlaceholder(self.displayPlaceholder) - } - } - } - let onUpdateDisplayPlaceholder: (Bool) -> Void + private(set) var displayPlaceholder: Bool = false + let onUpdateDisplayPlaceholder: (Bool, Double) -> Void init( item: Item?, context: AccountContext, groupId: String, attemptSynchronousLoad: Bool, - onUpdateDisplayPlaceholder: @escaping (Bool) -> Void + onUpdateDisplayPlaceholder: @escaping (Bool, Double) -> Void ) { self.item = item self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder super.init(context: context, file: item?.file, synchronousLoad: attemptSynchronousLoad) - self.updateDisplayPlaceholder(displayPlaceholder: true) + if item == nil { + self.updateDisplayPlaceholder(displayPlaceholder: true, duration: 0.0) + } self.started = { [weak self] in - self?.updateDisplayPlaceholder(displayPlaceholder: false) + let _ = self + //self?.updateDisplayPlaceholder(displayPlaceholder: false, duration: 0.2) } } @@ -359,8 +356,12 @@ public final class GifPagerContentComponent: Component { self.shouldBeAnimating = shouldBePlaying } - func updateDisplayPlaceholder(displayPlaceholder: Bool) { + func updateDisplayPlaceholder(displayPlaceholder: Bool, duration: Double) { + if self.displayPlaceholder == displayPlaceholder { + return + } self.displayPlaceholder = displayPlaceholder + self.onUpdateDisplayPlaceholder(displayPlaceholder, duration) } } @@ -402,6 +403,7 @@ public final class GifPagerContentComponent: Component { private let scrollView: ContentScrollView + private let placeholdersContainerView: UIView private var visibleItemPlaceholderViews: [ItemKey: ItemPlaceholderView] = [:] private var visibleItemLayers: [ItemKey: ItemLayer] = [:] private var ignoreScrolling: Bool = false @@ -417,6 +419,8 @@ public final class GifPagerContentComponent: Component { self.shimmerHostView = PortalSourceView() self.standaloneShimmerEffect = StandaloneShimmerEffect() + self.placeholdersContainerView = UIView() + self.scrollView = ContentScrollView() super.init(frame: frame) @@ -436,6 +440,8 @@ public final class GifPagerContentComponent: Component { self.scrollView.delegate = self self.addSubview(self.scrollView) + self.scrollView.addSubview(self.placeholdersContainerView) + self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) self.useSublayerTransformForActivation = false @@ -620,6 +626,12 @@ public final class GifPagerContentComponent: Component { } else { continue } + + if !component.isLoading { + if let placeholderView = self.visibleItemPlaceholderViews.removeValue(forKey: .placeholder(index)) { + self.visibleItemPlaceholderViews[itemId] = placeholderView + } + } validIds.insert(itemId) @@ -639,7 +651,7 @@ public final class GifPagerContentComponent: Component { context: component.context, groupId: "savedGif", attemptSynchronousLoad: attemptSynchronousLoads, - onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder in + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { return } @@ -651,7 +663,7 @@ public final class GifPagerContentComponent: Component { } else { placeholderView = ItemPlaceholderView(shimmerView: strongSelf.shimmerHostView) strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView - strongSelf.scrollView.insertSubview(placeholderView, at: 0) + strongSelf.placeholdersContainerView.addSubview(placeholderView) } placeholderView.frame = itemLayer.frame placeholderView.update(size: placeholderView.bounds.size) @@ -661,9 +673,20 @@ public final class GifPagerContentComponent: Component { } else { if let placeholderView = strongSelf.visibleItemPlaceholderViews[itemId] { strongSelf.visibleItemPlaceholderViews.removeValue(forKey: itemId) - placeholderView.removeFromSuperview() - - strongSelf.updateShimmerIfNeeded() + 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() + } } } } @@ -683,9 +706,13 @@ public final class GifPagerContentComponent: Component { itemTransition.setFrame(view: placeholderView, frame: itemFrame) placeholderView.update(size: itemFrame.size) } - } else if updateItemLayerPlaceholder { + } + + if updateItemLayerPlaceholder { if itemLayer.displayPlaceholder { - itemLayer.onUpdateDisplayPlaceholder(true) + itemLayer.onUpdateDisplayPlaceholder(true, 0.0) + } else { + itemLayer.onUpdateDisplayPlaceholder(false, 0.2) } } } @@ -708,7 +735,7 @@ public final class GifPagerContentComponent: Component { } private func updateShimmerIfNeeded() { - if self.visibleItemPlaceholderViews.isEmpty { + if self.placeholdersContainerView.subviews.isEmpty { self.standaloneShimmerEffect.layer = nil } else { self.standaloneShimmerEffect.layer = self.shimmerHostView.layer diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index 1b58dcbb53..97d36a4020 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -112,13 +112,19 @@ public final class TextNodeWithEntities { if let sourceString = arguments.attributedString { 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) + 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 itemSize = font.pointSize * 24.0 / 17.0 / CGFloat(min(2, range.length)) + 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, @@ -126,7 +132,7 @@ public final class TextNodeWithEntities { width: itemSize ) var callbacks = CTRunDelegateCallbacks( - version: kCTRunDelegateVersion1, + version: kCTRunDelegateCurrentVersion, dealloc: { dataRef in Unmanaged.fromOpaque(dataRef).release() }, @@ -143,12 +149,23 @@ public final class TextNodeWithEntities { return data.takeUnretainedValue().width } ) + if let runDelegate = CTRunDelegateCreate(&callbacks, Unmanaged.passRetained(runDelegateData).toOpaque()) { - string.addAttribute(NSAttributedString.Key(kCTRunDelegateAttributeName as String), value: runDelegate, range: range) + 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 } diff --git a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift index 6d81e65b0c..172113d076 100644 --- a/submodules/TextFormat/Sources/ChatTextInputAttributes.swift +++ b/submodules/TextFormat/Sources/ChatTextInputAttributes.swift @@ -23,6 +23,8 @@ public struct ChatTextInputAttributes { 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 { @@ -205,7 +207,8 @@ public final class ChatTextInputTextCustomEmojiAttribute: NSObject { override public func isEqual(_ object: Any?) -> Bool { if let other = object as? ChatTextInputTextCustomEmojiAttribute { - return self.stickerPack == other.stickerPack && self.fileId == other.fileId && self.file?.fileId == other.file?.fileId + return self === other + //return self.stickerPack == other.stickerPack && self.fileId == other.fileId && self.file?.fileId == other.file?.fileId } else { return false } 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() })) From 21b9ee462b7f26a35e97b4c3dc5541806762a83d Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 16 Jul 2022 18:00:37 +0200 Subject: [PATCH 058/113] Various fixes --- submodules/PremiumUI/Sources/PremiumDemoScreen.swift | 2 +- submodules/PremiumUI/Sources/PremiumIntroScreen.swift | 7 ++----- submodules/TelegramUI/Sources/ChatController.swift | 8 ++++++-- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index 6031f0cb16..2c80a1cb54 100644 --- a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift @@ -904,7 +904,7 @@ private final class DemoSheetContent: CombinedComponent { PageComponent( content: AnyComponent(PhoneDemoComponent( context: component.context, - position: .top, + position: .bottom, videoFile: configuration.videos["animated_emoji"], decoration: .emoji )), diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 1eda525bf1..823359e6bd 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -255,11 +255,11 @@ private struct PremiumIntroConfiguration { .noAds, .uniqueReactions, .premiumStickers, + .animatedEmoji, .advancedChatManagement, .profileBadge, .animatedUserpics, - .appIcons, - .animatedEmoji + .appIcons ]) } @@ -288,9 +288,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 diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index dd544f6faf..47c422d6e8 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1106,11 +1106,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G |> then( context.engine.stickers.resolveInlineStickers(fileIds: emojiFileIds) |> mapToSignal { files -> Signal in - var packReferences = Set() + 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 { - packReferences.insert(packReference) + if case let .id(id, _) = packReference, !existingIds.contains(id) { + packReferences.append(packReference) + existingIds.insert(id) + } break loop } } From 72bd0d31e2612fb251cd4894e2abf85f0dc0d797 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 16 Jul 2022 18:44:24 +0200 Subject: [PATCH 059/113] Various fixes --- submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift | 2 +- submodules/TelegramUI/Sources/ChatController.swift | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 51ddf3bf24..ac2a4bf7e8 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -1009,7 +1009,7 @@ private final class StickerPackContainer: ASDisplayNode { let layout = ItemLayout(width: fillingWidth, itemsCount: stickerPack.1.count, hasTitle: true) packsHeight += layout.height } - contentHeight = packsHeight + 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) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 47c422d6e8..a266da6424 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1100,6 +1100,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if !emojiFileIds.isEmpty { tip = .animatedEmoji(text: nil, arguments: nil, file: nil, action: nil) + actions.tip = tip disableTransitionAnimations = true actionsSignal = .single(actions) From 60e88c2c6c2d8026e539d9fbf5c52279c056a791 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 16 Jul 2022 19:36:56 +0200 Subject: [PATCH 060/113] Various fixes --- .../Sources/ContextActionsContainerNode.swift | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index ce4d024355..ace1b37389 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -349,6 +349,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { 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? @@ -408,6 +409,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 @@ -424,6 +430,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { self.addSubnode(self.highlightBackgroundNode) self.addSubnode(self.textNode.textNode) self.addSubnode(self.iconNode) + self.addSubnode(self.placeholderNode) self.textSelectionNode.flatMap(self.addSubnode) @@ -446,6 +453,16 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { 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 } @@ -511,14 +528,37 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { 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 - iconSize.width - 8.0, height: .greatestFiniteMagnitude), alignment: .left, lineSpacing: 0.0, cutout: nil, insets: UIEdgeInsets(), lineColor: nil, textShadowColor: nil, textStroke: nil)) + 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.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) From dbaf5d30d7e8e50e1187d610908774a19e96c3cd Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 17 Jul 2022 02:16:53 +0200 Subject: [PATCH 061/113] Emoji fixes --- submodules/ContextUI/Sources/ContextActionsContainerNode.swift | 2 +- submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index ace1b37389..0045400c43 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -509,7 +509,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { let iconSize = self.iconNode.image?.size ?? CGSize(width: 16.0, height: 16.0) - let text = self.text.replacingOccurrences(of: "#", with: "# ") + 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 }))) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index ac2a4bf7e8..576b23290f 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -324,7 +324,7 @@ private final class StickerPackContainer: ASDisplayNode { } let loadedStickerPacks = combineLatest(stickerPacks.map { - context.engine.stickers.loadedStickerPack(reference: $0, forceActualized: false) + 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 From c3f7e49e94dfeb180d2de3b76e6f592574931e87 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 17 Jul 2022 02:42:51 +0200 Subject: [PATCH 062/113] Various fixes --- .../Sources/State/PendingMessageManager.swift | 3 + .../TelegramUI/Sources/ChatController.swift | 66 +++++++++---------- .../Sources/ChatTextInputPanelNode.swift | 12 +++- 3 files changed, 44 insertions(+), 37 deletions(-) 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/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index a266da6424..0b352e0e31 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -7374,19 +7374,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G strongSelf.interfaceInteraction?.updateShowWebView { _ in return false } - - if !strongSelf.presentationInterfaceState.voiceMessagesAvailable { - if strongSelf.recordingModeFeedback == nil { - strongSelf.recordingModeFeedback = HapticFeedback() - strongSelf.recordingModeFeedback?.prepareError() - } - - strongSelf.chatDisplayNode.dismissInput() - - strongSelf.interfaceInteraction?.displayRestrictedInfo(.premiumVoiceMessages, .tooltip) - return - } - + let requestId = strongSelf.beginMediaRecordingRequestId let begin: () -> Void = { guard let strongSelf = self, strongSelf.beginMediaRecordingRequestId == requestId else { @@ -7555,29 +7543,34 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G } if case .premiumVoiceMessages = subject { - let rect = strongSelf.chatDisplayNode.frameForInputActionButton() - if let rect = rect { - strongSelf.mediaRestrictedTooltipController?.dismiss() - let text: String - if let peer = strongSelf.presentationInterfaceState.renderedPeer?.peer.flatMap({ EnginePeer($0) }) { - text = strongSelf.presentationInterfaceState.strings.Conversation_VoiceMessagesRestricted(peer.compactDisplayTitle).string - } else { - text = "" - } - 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 + 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 + })) } - } - 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() @@ -8934,6 +8927,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 { diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 692d82c6a2..132100c56a 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -694,7 +694,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 @@ -1895,7 +1901,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 From db450640ea7b407c431c744fe80f955bc04a3a3a Mon Sep 17 00:00:00 2001 From: Mike Renoir <> Date: Sun, 17 Jul 2022 13:57:49 +0200 Subject: [PATCH 063/113] fix equal bofinfo --- submodules/TelegramCore/Sources/SyncCore/SyncCore_BotInfo.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 } } From c141531c7be2365bd43df46ffc77c307077bd79b Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 19 Jul 2022 03:38:07 +0200 Subject: [PATCH 064/113] Animated emoji improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/AnimatedStickerNode.swift | 4 +- .../Sources/DirectAnimatedStickerNode.swift | 2 + .../AttachmentTextInputPanelNode.swift | 2 +- .../Sources/ChatListController.swift | 33 +- .../Source/Base/Transition.swift | 19 + .../Sources/LottieAnimationComponent.swift | 75 +- .../Sources/PagerComponent.swift | 12 + .../ContextUI/Sources/PeekController.swift | 5 + .../Sources/PeekControllerContent.swift | 2 + .../Sources/PeekControllerNode.swift | 2 + .../Sources/StickerPreviewPeekContent.swift | 17 + .../Sources/StickerPreviewPeekContent.swift | 23 + submodules/TelegramApi/Sources/Api0.swift | 7 +- submodules/TelegramApi/Sources/Api15.swift | 136 +-- submodules/TelegramApi/Sources/Api16.swift | 180 ++-- submodules/TelegramApi/Sources/Api17.swift | 84 ++ submodules/TelegramApi/Sources/Api20.swift | 54 + submodules/TelegramApi/Sources/Api26.swift | 42 +- submodules/TelegramApi/Sources/Api28.swift | 23 +- .../Components/MediaStreamComponent.swift | 10 +- .../PendingMessages/EnqueueMessage.swift | 21 + .../Sources/State/AccountViewTracker.swift | 53 +- ...onizeInstalledStickerPacksOperations.swift | 10 +- .../Sources/State/StickerManagement.swift | 166 ++- ...nchronizeRecentlyUsedMediaOperations.swift | 3 + .../SyncCore/SyncCore_Namespaces.swift | 2 + .../SyncCore/SyncCore_RecentMediaItem.swift | 103 ++ .../TelegramEngine/Payments/AppStore.swift | 2 +- .../Payments/BotPaymentForm.swift | 5 +- .../Stickers/SearchStickers.swift | 2 +- .../TelegramEngine/Stickers/StickerPack.swift | 2 +- .../Stickers/StickerSetInstallation.swift | 107 +- .../Stickers/TelegramEngineStickers.swift | 7 + .../DefaultDarkPresentationTheme.swift | 2 +- .../Resources/PresentationResourcesChat.swift | 2 +- .../Sources/AnimationCache.swift | 918 ++++++++++------- .../AudioTranscriptionButtonComponent.swift | 26 +- ...anscriptionPendingIndicatorComponent.swift | 10 +- .../Sources/EmojiPagerContentComponent.swift | 957 ++++++++++++++---- .../Sources/EntityKeyboard.swift | 57 +- ...tyKeyboardTopContainerPanelComponent.swift | 12 +- .../EntityKeyboardTopPanelComponent.swift | 412 ++++++-- .../Sources/GifPagerContentComponent.swift | 8 +- .../Sources/LottieAnimationCache.swift | 22 +- .../Sources/MultiAnimationMetalRenderer.swift | 44 +- .../Sources/MultiAnimationRenderer.swift | 357 +++++-- .../Sources/TextNodeWithEntities.swift | 2 +- .../Sources/VideoAnimationCache.swift | 3 +- .../PanelBadgeAdd.imageset/Contents.json | 12 + .../PanelBadgeAdd.imageset/addstickers.pdf | 103 ++ .../PanelBadgeLock.imageset/Contents.json | 12 + .../lockedstickers.pdf | 93 ++ .../ChatContextResultPeekContentNode.swift | 4 + .../TelegramUI/Sources/ChatController.swift | 2 + .../Sources/ChatControllerNode.swift | 23 +- .../Sources/ChatEntityKeyboardInputNode.swift | 279 ++++- .../Sources/ChatTextInputPanelNode.swift | 2 +- 58 files changed, 3446 insertions(+), 1133 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeAdd.imageset/addstickers.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelBadgeLock.imageset/lockedstickers.pdf diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index a044cdca39..2ec8127be1 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7849,3 +7849,5 @@ Sorry for the inconvenience."; "WebApp.CloseConfirmation" = "Changes that you made may not be saved."; "WebApp.CloseAnyway" = "Close Anyway"; + +"Emoji.ClearRecent" = "Clear Recent Emoji"; 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/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index 9d4a7ec421..925a02fd84 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -898,9 +898,9 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS let animationComponent = LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: "anim_smiletosticker", - colors: colors, mode: .animateTransitionFromPrevious ), + colors: colors, size: CGSize(width: 32.0, height: 32.0) ) let inputNodeSize = self.inputModeView.update( diff --git a/submodules/ChatListUI/Sources/ChatListController.swift b/submodules/ChatListUI/Sources/ChatListController.swift index 539cf35828..02ed9d2d8d 100644 --- a/submodules/ChatListUI/Sources/ChatListController.swift +++ b/submodules/ChatListUI/Sources/ChatListController.swift @@ -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/ComponentFlow/Source/Base/Transition.swift b/submodules/ComponentFlow/Source/Base/Transition.swift index c21d1afcf7..c2ca5bc861 100644 --- a/submodules/ComponentFlow/Source/Base/Transition.swift +++ b/submodules/ComponentFlow/Source/Base/Transition.swift @@ -458,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 { diff --git a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift index 8c773c16df..df3e9b90a5 100644 --- a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift +++ b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift @@ -20,21 +20,21 @@ public final class LottieAnimationComponent: Component { 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 } @@ -42,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 ) @@ -51,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 } @@ -117,6 +121,11 @@ 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 + } if self.component?.animation != component.animation { if let animationView = self.animationView { @@ -158,15 +167,7 @@ public final class LottieAnimationComponent: Component { view.backgroundColor = .clear view.isOpaque = false - if let value = component.animation.colors["__allcolors__"] { - for keypath in view.allKeypaths(predicate: { $0.keys.last == "Color" }) { - view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: keypath)) - } - } - - for (key, value) in component.animation.colors { - view.setValueProvider(ColorValueProvider(value.lottieColorValue), keypath: AnimationKeypath(keypath: "\(key).Color")) - } + updateColors = true self.animationView = view self.addSubview(view) @@ -176,6 +177,23 @@ public final class LottieAnimationComponent: Component { } } + 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 @@ -187,7 +205,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 && !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 { diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index b3b0ce76ce..d6db0ca729 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -261,6 +261,10 @@ public final class PagerComponent View { diff --git a/submodules/ContextUI/Sources/PeekController.swift b/submodules/ContextUI/Sources/PeekController.swift index 2bacd9ad6f..615979d884 100644 --- a/submodules/ContextUI/Sources/PeekController.swift +++ b/submodules/ContextUI/Sources/PeekController.swift @@ -68,6 +68,11 @@ public final class PeekController: ViewController, ContextControllerProtocol { private var animatedIn = false + 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 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/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/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/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift b/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift index 07dbc281d7..1eeef0f26a 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPreviewPeekContent.swift @@ -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/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 37050808eb..daf94bbb99 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -544,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) } @@ -710,6 +711,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[313694676] = { return Api.StickerPack.parse_stickerPack($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) } @@ -805,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) } @@ -1003,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[1288001087] = { 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) } @@ -1418,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: diff --git a/submodules/TelegramApi/Sources/Api15.swift b/submodules/TelegramApi/Sources/Api15.swift index d25de327ff..b797c99619 100644 --- a/submodules/TelegramApi/Sources/Api15.swift +++ b/submodules/TelegramApi/Sources/Api15.swift @@ -326,6 +326,46 @@ public extension Api { } } +public extension Api { + enum PaymentFormMethod: TypeConstructorDescription { + case paymentFormMethod(url: String, title: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paymentFormMethod(let url, let title): + if boxed { + 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?) @@ -1228,99 +1268,3 @@ public extension Api { } } -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!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api16.swift b/submodules/TelegramApi/Sources/Api16.swift index 830291d176..2c3236c9e6 100644 --- a/submodules/TelegramApi/Sources/Api16.swift +++ b/submodules/TelegramApi/Sources/Api16.swift @@ -1,3 +1,99 @@ +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!) + } + else { + return nil + } + } + + } +} public extension Api { enum PhotoSize: TypeConstructorDescription { case photoCachedSize(type: String, w: Int32, h: Int32, bytes: Buffer) @@ -848,87 +944,3 @@ public extension Api { } } -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!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api17.swift b/submodules/TelegramApi/Sources/Api17.swift index 31892c8e6f..6fbc72af8f 100644 --- a/submodules/TelegramApi/Sources/Api17.swift +++ b/submodules/TelegramApi/Sources/Api17.swift @@ -1,3 +1,87 @@ +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!) + } + else { + return nil + } + } + + } +} public extension Api { enum RecentMeUrl: TypeConstructorDescription { case recentMeUrlChat(url: String, chatId: Int64) diff --git a/submodules/TelegramApi/Sources/Api20.swift b/submodules/TelegramApi/Sources/Api20.swift index ca0fd02867..b6b4d1684b 100644 --- a/submodules/TelegramApi/Sources/Api20.swift +++ b/submodules/TelegramApi/Sources/Api20.swift @@ -87,6 +87,7 @@ public extension Api { public extension Api { 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) { @@ -98,6 +99,22 @@ public extension Api { 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) @@ -116,6 +133,8 @@ public extension Api { switch self { 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))]) } @@ -139,6 +158,29 @@ public extension Api { 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() { @@ -592,6 +634,7 @@ public extension Api { 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) @@ -1332,6 +1375,12 @@ public extension Api { } 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 { @@ -1660,6 +1709,8 @@ public extension Api { 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): @@ -3196,6 +3247,9 @@ public extension Api { 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 } diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index 9dadf48c72..2d4247b260 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -728,13 +728,13 @@ public extension Api.payments { } 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]) + 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 savedInfo, let savedCredentials, let users): + 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(-1340916937) + buffer.appendInt32(1288001087) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt64(formId, buffer: buffer, boxed: false) @@ -747,6 +747,11 @@ public extension Api.payments { 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 {savedCredentials!.serialize(buffer, true)} buffer.appendInt32(481674261) @@ -760,8 +765,8 @@ public extension Api.payments { 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))]) + 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))]) } } @@ -794,17 +799,21 @@ public extension Api.payments { 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? + 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() { - _12 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo + _13 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo } } - var _13: Api.PaymentSavedCredentials? + var _14: Api.PaymentSavedCredentials? if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _13 = Api.parse(reader, signature: signature) as? Api.PaymentSavedCredentials + _14 = Api.parse(reader, signature: signature) as? Api.PaymentSavedCredentials } } - var _14: [Api.User]? + var _15: [Api.User]? if let _ = reader.readInt32() { - _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) } let _c1 = _1 != nil let _c2 = _2 != nil @@ -817,11 +826,12 @@ public extension Api.payments { 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!) + 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 diff --git a/submodules/TelegramApi/Sources/Api28.swift b/submodules/TelegramApi/Sources/Api28.swift index 1f202e0395..220dbe1deb 100644 --- a/submodules/TelegramApi/Sources/Api28.swift +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -4215,6 +4215,21 @@ public extension Api.functions.messages { }) } } +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() @@ -6295,11 +6310,11 @@ public extension Api.functions.payments { } } public extension Api.functions.payments { - static func canPurchasePremium() -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func canPurchasePremium(purpose: Api.InputStorePaymentPurpose) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(-1435856696) - - return (FunctionDescription(name: "payments.canPurchasePremium", parameters: []), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in + 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() { diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index 6657ba966a..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(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))), ])), diff --git a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift index 9c8ebeaf60..d2b70fb1e6 100644 --- a/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift +++ b/submodules/TelegramCore/Sources/PendingMessages/EnqueueMessage.swift @@ -351,6 +351,7 @@ func enqueueMessages(transaction: Transaction, account: Account, peerId: PeerId, } var addedHashtags: [String] = [] + var emojiItems: [RecentEmojiItem] = [] var localGroupingKeyBySourceKey: [Int64: Int64] = [:] @@ -475,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 @@ -786,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/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/ManagedSynchronizeInstalledStickerPacksOperations.swift b/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift index bd5ca0c408..30ebc429d2 100644 --- a/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift +++ b/submodules/TelegramCore/Sources/State/ManagedSynchronizeInstalledStickerPacksOperations.swift @@ -220,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 diff --git a/submodules/TelegramCore/Sources/State/StickerManagement.swift b/submodules/TelegramCore/Sources/State/StickerManagement.swift index 6ed01b4b11..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 @@ -24,9 +48,9 @@ func manageStickerPacks(network: Network, postbox: Postbox) -> Signal 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)! @@ -37,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 @@ -56,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 { @@ -64,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> { @@ -85,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 @@ -125,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/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/SyncCore/SyncCore_Namespaces.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift index e50e1cefde..21b6d87f87 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_Namespaces.swift @@ -64,6 +64,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 { 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/TelegramEngine/Payments/AppStore.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift index 02d4e6ac9c..125cf90fad 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/AppStore.swift @@ -59,7 +59,7 @@ public enum RestoreAppStoreReceiptError { } func _internal_canPurchasePremium(account: Account) -> Signal { - return account.network.request(Api.functions.payments.canPurchasePremium()) + return account.network.request(Api.functions.payments.canPurchasePremium(purpose: .inputStorePaymentPremiumSubscription(flags: 0))) |> map { result -> Bool in switch result { case .boolTrue: diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift index 4518080812..547c67571f 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift @@ -213,7 +213,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,10 +266,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 + let _ = additionalMethods var peers: [Peer] = [] for user in apiUsers { 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 ec51d20bd3..4fb16e89f7 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPack.swift @@ -105,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/StickerSetInstallation.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift index 57f9fbc734..a09adceb7e 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerSetInstallation.swift @@ -140,64 +140,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 6572932b23..936b704f76 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift @@ -133,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) diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 1257695a51..331c154d89 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( diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index e7e93439fb..280bae0544 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -373,7 +373,7 @@ 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)) + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/GridDismissIcon"), color: theme.chat.inputMediaPanel.stickersSectionTextColor) }) } diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 09c9af7a1c..5e6e58c568 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -47,29 +47,21 @@ public final class AnimationCacheItemFrame { } public final class AnimationCacheItem { + public enum Advance { + case duration(Double) + case frames(Int) + } + public let numFrames: Int - private let getFrameImpl: (Int, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? - private let getFrameIndexImpl: (Double) -> Int - private let getFrameDurationImpl: (Int) -> Double? + private let advanceImpl: (Advance, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? - public init(numFrames: Int, getFrame: @escaping (Int, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame?, getFrameIndexImpl: @escaping (Double) -> Int, getFrameDurationImpl: @escaping (Int) -> Double?) { + public init(numFrames: Int, advanceImpl: @escaping (Advance, AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame?) { self.numFrames = numFrames - self.getFrameImpl = getFrame - self.getFrameIndexImpl = getFrameIndexImpl - self.getFrameDurationImpl = getFrameDurationImpl + self.advanceImpl = advanceImpl } - public func getFrameDuration(index: Int) -> Double? { - return self.getFrameDurationImpl(index) - } - - public func getFrame(index: Int, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { - return self.getFrameImpl(index, requestedFormat) - } - - public func getFrame(at duration: Double, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { - let index = self.getFrameIndexImpl(duration) - return self.getFrameImpl(index, requestedFormat) + public func advance(advance: Advance, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { + return self.advanceImpl(advance, requestedFormat) } } @@ -99,7 +91,7 @@ public protocol AnimationCacheItemWriter: AnyObject { var queue: Queue { get } var isCancelled: Bool { get } - func add(with drawingBlock: (AnimationCacheItemDrawingSurface) -> Void, proposedWidth: Int, proposedHeight: Int, duration: Double) + func add(with drawingBlock: (AnimationCacheItemDrawingSurface) -> Double?, proposedWidth: Int, proposedHeight: Int) func finish() } @@ -216,21 +208,23 @@ private func decompressData(data: Data, range: Range, decompressedSize: Int } 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 } var isCancelled: Bool = false - private let decompressedPath: String private let compressedPath: String - private var file: ManagedFile? + private let file: ManagedFile + private let compressedWriter: CompressedFileWriter private var currentYUVASurface: ImageYUVA420? private var currentDctData: DctData? @@ -240,28 +234,30 @@ private final class AnimationCacheItemWriterInternal { private var isFinished: Bool = false private var frames: [FrameMetadata] = [] - private var contentLength: Int = 0 private let dctQuality: Int init?(allocateTempFile: @escaping () -> String) { self.dctQuality = 70 - self.decompressedPath = allocateTempFile() self.compressedPath = allocateTempFile() - guard let file = ManagedFile(queue: nil, path: self.decompressedPath, mode: .readwrite) else { + 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) -> Void, proposedWidth: Int, proposedHeight: Int, duration: Double) { + func add(with drawingBlock: (ImageYUVA420) -> Double?, proposedWidth: Int, proposedHeight: Int) throws { if self.isFailed || self.isFinished { return } - guard !self.isFailed, !self.isFinished, let file = self.file else { + guard !self.isFailed, !self.isFinished else { return } @@ -305,24 +301,27 @@ private final class AnimationCacheItemWriterInternal { self.currentDctData = dctData } - drawingBlock(yuvaSurface) + let duration = drawingBlock(yuvaSurface) + + guard let duration = duration else { + return + } yuvaSurface.dct(dctData: dctData, target: dctCoefficients) if isFirstFrame { - file.write(2 as UInt32) + self.file.write(3 as UInt32) - file.write(UInt32(dctCoefficients.yPlane.width)) - file.write(UInt32(dctCoefficients.yPlane.height)) - file.write(UInt32(dctData.quality)) + self.file.write(UInt32(dctCoefficients.yPlane.width)) + self.file.write(UInt32(dctCoefficients.yPlane.height)) + self.file.write(UInt32(dctData.quality)) - self.contentLengthOffset = Int(file.position()) - file.write(0 as UInt32) + self.contentLengthOffset = Int(self.file.position()) + self.file.write(0 as UInt32) } - let framePosition = Int(file.position()) - assert(framePosition >= 0) - var frameLength = 0 + 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 @@ -339,85 +338,63 @@ private final class AnimationCacheItemWriterInternal { preconditionFailure() } - dctPlane.data.withUnsafeBytes { bytes in - let _ = file.write(bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: bytes.count) + 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) } - frameLength += dctPlane.data.count } - self.frames.append(FrameMetadata(offset: framePosition, length: frameLength, duration: duration)) - - self.contentLength += frameLength + self.frames.append(FrameMetadata(duration: duration)) } - func finish() -> CompressedResult? { + func finish() throws -> CompressedResult { var shouldComplete = false - outer: for _ in 0 ..< 1 { + do { if !self.isFinished { self.isFinished = true shouldComplete = true - guard let contentLengthOffset = self.contentLengthOffset, let file = self.file else { + try self.compressedWriter.flush() + + guard let contentLengthOffset = self.contentLengthOffset else { self.isFailed = true - break outer + throw WriteError.generic } assert(contentLengthOffset >= 0) let metadataPosition = file.position() + let contentLength = Int(metadataPosition) - contentLengthOffset - 4 file.seek(position: Int64(contentLengthOffset)) - file.write(UInt32(self.contentLength)) + file.write(UInt32(contentLength)) file.seek(position: metadataPosition) file.write(UInt32(self.frames.count)) for frame in self.frames { - file.write(UInt32(frame.offset)) - file.write(UInt32(frame.length)) file.write(Float32(frame.duration)) } if !self.frames.isEmpty { } else { self.isFailed = true - break outer + throw WriteError.generic } - if !self.isFailed { - self.file = nil - - file._unsafeClose() - - guard let uncompressedData = try? Data(contentsOf: URL(fileURLWithPath: self.decompressedPath), options: .alwaysMapped) else { - self.isFailed = true - break outer - } - guard let compressedData = compressData(data: uncompressedData) else { - self.isFailed = true - break outer - } - guard let compressedFile = ManagedFile(queue: nil, path: self.compressedPath, mode: .readwrite) else { - self.isFailed = true - break outer - } - compressedFile.write(Int32(uncompressedData.count)) - let _ = compressedFile.write(compressedData) - compressedFile._unsafeClose() - } + self.file._unsafeClose() } + } catch let e { + throw e } if shouldComplete { - let _ = try? FileManager.default.removeItem(atPath: self.decompressedPath) - if !self.isFailed { return CompressedResult(path: self.compressedPath) } else { let _ = try? FileManager.default.removeItem(atPath: self.compressedPath) - - return nil + throw WriteError.generic } } else { - return nil + throw WriteError.generic } } } @@ -425,22 +402,18 @@ private final class AnimationCacheItemWriterInternal { private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { struct CompressedResult { var animationPath: String - var firstFramePath: String } private struct FrameMetadata { - var offset: Int - var length: Int var duration: Double } let queue: Queue var isCancelled: Bool = false - private let decompressedPath: String private let compressedPath: String - private let firstFramePath: String private var file: ManagedFile? + private var compressedWriter: CompressedFileWriter? private let completion: (CompressedResult?) -> Void private var currentSurface: ImageARGB? @@ -452,7 +425,6 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { private var isFinished: Bool = false private var frames: [FrameMetadata] = [] - private var contentLength: Int = 0 private let dctQuality: Int @@ -462,24 +434,23 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { self.dctQuality = 70 self.queue = queue - self.decompressedPath = allocateTempFile() self.compressedPath = allocateTempFile() - self.firstFramePath = allocateTempFile() - guard let file = ManagedFile(queue: nil, path: self.decompressedPath, mode: .readwrite) else { + 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(with drawingBlock: (AnimationCacheItemDrawingSurface) -> Void, proposedWidth: Int, proposedHeight: Int, duration: Double) { + func add(with drawingBlock: (AnimationCacheItemDrawingSurface) -> Double?, proposedWidth: Int, proposedHeight: Int) { if self.isFailed || self.isFinished { return } self.lock.locked { - guard !self.isFailed, !self.isFinished, let file = self.file else { + guard !self.isFailed, !self.isFinished, let file = self.file, let compressedWriter = self.compressedWriter else { return } @@ -537,8 +508,8 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { self.currentDctData = dctData } - surface.argbPlane.data.withUnsafeMutableBytes { bytes -> Void in - drawingBlock(AnimationCacheItemDrawingSurface( + let duration = surface.argbPlane.data.withUnsafeMutableBytes { bytes -> Double? in + return drawingBlock(AnimationCacheItemDrawingSurface( argb: bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), width: width, height: height, @@ -547,11 +518,15 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { )) } + guard let duration = duration else { + return + } + surface.toYUVA420(target: yuvaSurface) yuvaSurface.dct(dctData: dctData, target: dctCoefficients) if isFirstFrame { - file.write(2 as UInt32) + file.write(3 as UInt32) file.write(UInt32(dctCoefficients.yPlane.width)) file.write(UInt32(dctCoefficients.yPlane.height)) @@ -561,34 +536,35 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { file.write(0 as UInt32) } - let framePosition = Int(file.position()) - assert(framePosition >= 0) - var frameLength = 0 - - 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() + 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) + } } - dctPlane.data.withUnsafeBytes { bytes in - let _ = file.write(bytes.baseAddress!.assumingMemoryBound(to: UInt8.self), count: bytes.count) - } - frameLength += dctPlane.data.count + self.frames.append(FrameMetadata(duration: duration)) + } catch { + self.isFailed = true } - - self.frames.append(FrameMetadata(offset: framePosition, length: frameLength, duration: duration)) - - self.contentLength += frameLength } } @@ -599,94 +575,43 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { self.isFinished = true shouldComplete = true - guard let contentLengthOffset = self.contentLengthOffset, let file = self.file else { + guard let contentLengthOffset = self.contentLengthOffset, let file = self.file, let compressedWriter = self.compressedWriter else { self.isFailed = true return } assert(contentLengthOffset >= 0) - let metadataPosition = file.position() - file.seek(position: Int64(contentLengthOffset)) - file.write(UInt32(self.contentLength)) + do { + try compressedWriter.flush() - file.seek(position: metadataPosition) - file.write(UInt32(self.frames.count)) - for frame in self.frames { - file.write(UInt32(frame.offset)) - file.write(UInt32(frame.length)) - file.write(Float32(frame.duration)) - } - - if !self.frames.isEmpty, let dctCoefficients = self.currentDctCoefficients, let dctData = self.currentDctData { - var firstFrameData = Data(capacity: 4 * 5 + self.frames[0].length) + let metadataPosition = file.position() + let contentLength = Int(metadataPosition) - contentLengthOffset - 4 + file.seek(position: Int64(contentLengthOffset)) + file.write(UInt32(contentLength)) - writeUInt32(data: &firstFrameData, value: 2 as UInt32) - writeUInt32(data: &firstFrameData, value: UInt32(dctCoefficients.yPlane.width)) - writeUInt32(data: &firstFrameData, value: UInt32(dctCoefficients.yPlane.height)) - writeUInt32(data: &firstFrameData, value: UInt32(dctData.quality)) - - writeUInt32(data: &firstFrameData, value: UInt32(self.frames[0].length)) - let firstFrameStart = 4 * 5 - - file.seek(position: Int64(self.frames[0].offset)) - firstFrameData.count += self.frames[0].length - firstFrameData.withUnsafeMutableBytes { bytes in - let _ = file.read(bytes.baseAddress!.advanced(by: 4 * 5), self.frames[0].length) + file.seek(position: metadataPosition) + file.write(UInt32(self.frames.count)) + for frame in self.frames { + file.write(Float32(frame.duration)) } - writeUInt32(data: &firstFrameData, value: UInt32(1)) - writeUInt32(data: &firstFrameData, value: UInt32(firstFrameStart)) - writeUInt32(data: &firstFrameData, value: UInt32(self.frames[0].length)) - writeFloat32(data: &firstFrameData, value: Float32(1.0)) - - guard let compressedFirstFrameData = compressData(data: firstFrameData, addSizeHeader: true) else { - self.isFailed = true - return + if !self.isFailed { + self.compressedWriter = nil + self.file = nil + + file._unsafeClose() } - guard let _ = try? compressedFirstFrameData.write(to: URL(fileURLWithPath: self.firstFramePath)) else { - self.isFailed = true - return - } - } else { + } catch { self.isFailed = true - return - } - - if !self.isFailed { - self.file = nil - - file._unsafeClose() - - guard let uncompressedData = try? Data(contentsOf: URL(fileURLWithPath: self.decompressedPath), options: .alwaysMapped) else { - self.isFailed = true - return - } - guard let compressedData = compressData(data: uncompressedData) else { - self.isFailed = true - return - } - guard let compressedFile = ManagedFile(queue: nil, path: self.compressedPath, mode: .readwrite) else { - self.isFailed = true - return - } - compressedFile.write(Int32(uncompressedData.count)) - let _ = compressedFile.write(compressedData) - compressedFile._unsafeClose() } } } if shouldComplete { - let _ = try? FileManager.default.removeItem(atPath: self.decompressedPath) - if !self.isFailed { - self.completion(CompressedResult( - animationPath: self.compressedPath, - firstFramePath: self.firstFramePath - )) + self.completion(CompressedResult(animationPath: self.compressedPath)) } else { let _ = try? FileManager.default.removeItem(atPath: self.compressedPath) - let _ = try? FileManager.default.removeItem(atPath: self.firstFramePath) self.completion(nil) } } @@ -694,73 +619,165 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { } 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 width: Int + private let height: Int private let durationMapping: [Double] - private let totalDuration: Double + + private var currentFrame: CurrentFrame? private var currentYUVASurface: ImageYUVA420? private var currentDctData: DctData - private var currentDctCoefficients: DctCoefficientsYUVA420 + private var sharedDctCoefficients: DctCoefficientsYUVA420? - init(data: Data, frameMapping: [FrameInfo], width: Int, height: Int, dctQuality: Int) { + init(data: Data, range: Range, frameMapping: [FrameInfo], width: Int, height: Int, dctQuality: Int) { self.data = data + self.range = range + self.width = width + self.height = height var resultFrameMapping: [Int: FrameInfo] = [:] var durationMapping: [Double] = [] - var totalDuration: Double = 0.0 for i in 0 ..< frameMapping.count { let frame = frameMapping[i] resultFrameMapping[i] = frame - totalDuration += frame.duration - durationMapping.append(totalDuration) + durationMapping.append(frame.duration) } self.frameMapping = resultFrameMapping self.durationMapping = durationMapping - self.totalDuration = totalDuration self.currentDctData = DctData(quality: dctQuality) - self.currentDctCoefficients = DctCoefficientsYUVA420(width: width, height: height) } - func getFrame(index: Int, requestedFormat: AnimationCacheItemFrame.RequestedFormat) -> AnimationCacheItemFrame? { - guard let frameInfo = self.frameMapping[index] else { - return nil + 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 } - var frameDataOffset = 0 - let frameLength = frameInfo.range.upperBound - frameInfo.range.lowerBound - for i in 0 ..< 4 { - let dctPlane: DctCoefficientPlane - switch i { - case 0: - dctPlane = self.currentDctCoefficients.yPlane - case 1: - dctPlane = self.currentDctCoefficients.uPlane - case 2: - dctPlane = self.currentDctCoefficients.vPlane - case 3: - dctPlane = self.currentDctCoefficients.aPlane - default: - preconditionFailure() + 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 } - if frameDataOffset + dctPlane.data.count > frameLength { - break + 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 } - dctPlane.data.withUnsafeMutableBytes { targetBuffer -> Void in - self.data.copyBytes(to: targetBuffer.baseAddress!.assumingMemoryBound(to: UInt8.self), from: (frameInfo.range.lowerBound + frameDataOffset) ..< (frameInfo.range.lowerBound + frameDataOffset + targetBuffer.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() } - - frameDataOffset += dctPlane.data.count + 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 } let yuvaSurface: ImageYUVA420 @@ -769,13 +786,13 @@ private final class AnimationCacheItemAccessor { if let currentYUVASurface = self.currentYUVASurface { yuvaSurface = currentYUVASurface } else { - yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, rowAlignment: nil) + yuvaSurface = ImageYUVA420(width: currentFrame.dctCoefficients.yPlane.width, height: currentFrame.dctCoefficients.yPlane.height, rowAlignment: nil) } case let .yuva(preferredRowAlignment): - yuvaSurface = ImageYUVA420(width: self.currentDctCoefficients.yPlane.width, height: self.currentDctCoefficients.yPlane.height, rowAlignment: preferredRowAlignment) + yuvaSurface = ImageYUVA420(width: currentFrame.dctCoefficients.yPlane.width, height: currentFrame.dctCoefficients.yPlane.height, rowAlignment: preferredRowAlignment) } - self.currentDctCoefficients.idct(dctData: self.currentDctData, target: yuvaSurface) + currentFrame.dctCoefficients.idct(dctData: self.currentDctData, target: yuvaSurface) switch requestedFormat { case .rgba: @@ -783,7 +800,7 @@ private final class AnimationCacheItemAccessor { 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: frameInfo.duration) + 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( @@ -812,34 +829,10 @@ private final class AnimationCacheItemAccessor { bytesPerRow: yuvaSurface.aPlane.bytesPerRow ) ), - duration: frameInfo.duration + duration: currentFrame.duration ) } } - - func getFrameIndex(duration: Double) -> Int { - if self.totalDuration == 0.0 { - return 0 - } - if self.durationMapping.count <= 1 { - return 0 - } - let normalizedDuration = duration.truncatingRemainder(dividingBy: self.totalDuration) - for i in 1 ..< self.durationMapping.count { - if normalizedDuration < self.durationMapping[i] { - return i - 1 - } - } - return self.durationMapping.count - 1 - } - - func getFrameDuration(index: Int) -> Double? { - if index < self.durationMapping.count { - return self.durationMapping[index] - } else { - return nil - } - } } private func readUInt32(data: Data, offset: Int) -> UInt32 { @@ -884,137 +877,344 @@ private func writeFloat32(data: inout Data, value: Float32) { }) } -private func loadItem(path: String) -> AnimationCacheItem? { - guard let compressedData = try? Data(contentsOf: URL(fileURLWithPath: path), options: .alwaysMapped) else { - return nil +private final class CompressedFileWriter { + enum WriteError: Error { + case generic } - if compressedData.count < 4 { - return nil - } - let decompressedSize = readUInt32(data: compressedData, offset: 0) + private let file: ManagedFile + private let stream: UnsafeMutablePointer - if decompressedSize <= 0 || decompressedSize > 40 * 1024 * 1024 { - return nil - } - guard let data = decompressData(data: compressedData, range: 4 ..< compressedData.count, decompressedSize: Int(decompressedSize)) else { - return nil - } + private let tempBufferSize: Int = 32 * 1024 + private let tempBuffer: UnsafeMutablePointer - let dataLength = data.count + private var didFail: Bool = false - var offset = 0 - - guard dataLength >= offset + 4 else { - return nil - } - let formatVersion = readUInt32(data: data, offset: offset) - offset += 4 - if formatVersion != 2 { - return nil - } - - guard dataLength >= offset + 4 else { - return nil - } - let width = readUInt32(data: data, offset: offset) - offset += 4 - - guard dataLength >= offset + 4 else { - return nil - } - let height = readUInt32(data: data, offset: offset) - offset += 4 - - guard dataLength >= offset + 4 else { - return nil - } - let dctQuality = readUInt32(data: data, offset: offset) - offset += 4 - - 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: [AnimationCacheItemAccessor.FrameInfo] = [] - for _ 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 = readFloat32(data: data, offset: offset) - offset += 4 - - frameMapping.append(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, width: Int(width), height: Int(height), dctQuality: Int(dctQuality)) + deinit { + compression_stream_destroy(self.stream) + self.stream.deallocate() + self.tempBuffer.deallocate() + } - return AnimationCacheItem(numFrames: Int(numFrames), getFrame: { index, requestedFormat in - return itemAccessor.getFrame(index: index, requestedFormat: requestedFormat) - }, getFrameIndexImpl: { duration in - return itemAccessor.getFrameIndex(duration: duration) - }, getFrameDurationImpl: { index in - return itemAccessor.getFrameDuration(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 != 3 { + 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 dctQuality = readUInt32(data: compressedData, offset: offset) + offset += 4 + + 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))) + } + + let itemAccessor = AnimationCacheItemAccessor(data: compressedData, range: compressedFrameDataRange, frameMapping: frameMapping, width: Int(width), height: Int(height), dctQuality: Int(dctQuality)) + + 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 = loadItem(path: higherResolutionPath) else { + guard let higherResolutionItem = try? loadItem(path: higherResolutionPath) else { return nil } guard let writer = AnimationCacheItemWriterInternal(allocateTempFile: allocateTempFile) else { return nil } - for i in 0 ..< higherResolutionItem.numFrames { - guard let duration = higherResolutionItem.getFrameDuration(index: i) else { - break + 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) } - writer.add(with: { yuva in - guard let frame = higherResolutionItem.getFrame(index: i, requestedFormat: .yuva(rowAlignment: yuva.yPlane.rowAlignment)) else { - return + + 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 + return false 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) + 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) } - }, proposedWidth: width, proposedHeight: height, duration: duration) + } + + 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 } - - guard let result = writer.finish() else { - return nil - } - 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 = loadItem(path: itemPath) else { - return nil - } - return item } private func findHigherResolutionFileForAdaptation(itemDirectoryPath: String, baseName: String, baseSuffix: String, width: Int, height: Int) -> String? { @@ -1106,7 +1306,7 @@ public final class AnimationCacheImpl: AnimationCache { let itemPath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)" let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" - if FileManager.default.fileExists(atPath: itemPath), let item = loadItem(path: itemPath) { + if FileManager.default.fileExists(atPath: itemPath), let item = try? loadItem(path: itemPath) { updateResult(AnimationCacheItemResult(item: item, isFinal: true)) return EmptyDisposable @@ -1130,6 +1330,7 @@ public final class AnimationCacheImpl: AnimationCache { if beginFetch { 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 { @@ -1148,11 +1349,10 @@ public final class AnimationCacheImpl: AnimationCache { guard let _ = try? FileManager.default.moveItem(atPath: result.animationPath, toPath: itemPath) else { return } - let _ = try? FileManager.default.removeItem(atPath: itemFirstFramePath) - guard let _ = try? FileManager.default.moveItem(atPath: result.firstFramePath, toPath: itemFirstFramePath) 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 } @@ -1197,7 +1397,7 @@ public final class AnimationCacheImpl: AnimationCache { let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" if FileManager.default.fileExists(atPath: itemFirstFramePath) { - return loadItem(path: itemFirstFramePath) + return try? loadItem(path: itemFirstFramePath) } if let adaptationItemPath = findHigherResolutionFileForAdaptation(itemDirectoryPath: itemDirectoryPath, baseName: "\(hashString)_", baseSuffix: "-f", width: Int(size.width), height: Int(size.height)) { @@ -1215,7 +1415,7 @@ public final class AnimationCacheImpl: AnimationCache { let itemDirectoryPath = "\(basePath)/\(sourceIdPath.directory)" let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" - if FileManager.default.fileExists(atPath: itemFirstFramePath), let item = loadItem(path: itemFirstFramePath) { + if FileManager.default.fileExists(atPath: itemFirstFramePath), let item = try? loadItem(path: itemFirstFramePath) { completion(item) return EmptyDisposable } diff --git a/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift b/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift index 9965a8ca92..d4cf07ff4e 100644 --- a/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift +++ b/submodules/TelegramUI/Components/AudioTranscriptionButtonComponent/Sources/AudioTranscriptionButtonComponent.swift @@ -110,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: {}, @@ -142,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/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index be5edb1358..7b1bf8d1a9 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -26,16 +26,30 @@ 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 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() - self.iconLayer.contents = premiumBadgeIcon?.cgImage super.init(frame: CGRect()) + self.layer.addSublayer(self.contentLayer) + self.layer.addSublayer(self.overlayColorLayer) self.layer.addSublayer(self.iconLayer) } @@ -43,27 +57,62 @@ private final class PremiumBadgeView: UIView { fatalError("init(coder:) has not been implemented") } - func update(backgroundColor: UIColor, size: CGSize) { - //self.updateColor(color: backgroundColor, transition: .immediate) - self.backgroundColor = backgroundColor - self.layer.cornerRadius = size.width / 2.0 + 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 + } + } - self.iconLayer.frame = CGRect(origin: CGPoint(), size: size).insetBy(dx: 2.0, dy: 2.0) + let iconInset: CGFloat + switch badge { + case .premium: + iconInset = 2.0 + case .featured: + iconInset = 0.0 + case .locked: + iconInset = 0.0 + } - //super.update(size: size, cornerRadius: min(size.width / 2.0, size.height / 2.0), transition: .immediate) + 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 GroupHeaderLayer: SimpleLayer { + private let textLayer: SimpleLayer private var lockIconLayer: SimpleLayer? + private(set) var clearIconLayer: SimpleLayer? + + private var theme: PresentationTheme? private var currentTextLayout: (string: String, color: UIColor, constrainedWidth: CGFloat, size: CGSize)? override init() { + self.textLayer = SimpleLayer() + super.init() + + self.addSublayer(self.textLayer) } override init(layer: Any) { + self.textLayer = SimpleLayer() + super.init(layer: layer) } @@ -71,11 +120,17 @@ private final class GroupHeaderLayer: SimpleLayer { fatalError("init(coder:) has not been implemented") } - func update(theme: PresentationTheme, title: String, isPremium: Bool, constrainedWidth: CGFloat) -> (size: CGSize, horizontalOffset: CGFloat) { + func update(theme: PresentationTheme, title: String, isPremiumLocked: Bool, hasClear: Bool, constrainedWidth: CGFloat) -> CGSize { + var themeUpdated = false + if self.theme !== theme { + self.theme = theme + themeUpdated = true + } + let color = theme.chat.inputMediaPanel.stickersSectionTextColor - let horizontalOffset: CGFloat - if isPremium { + let titleHorizontalOffset: CGFloat + if isPremiumLocked { let lockIconLayer: SimpleLayer if let current = self.lockIconLayer { lockIconLayer = current @@ -87,38 +142,67 @@ private final class GroupHeaderLayer: SimpleLayer { if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme) { let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0)) lockIconLayer.contents = image.cgImage - horizontalOffset = imageSize.width + 2.0 - lockIconLayer.frame = CGRect(origin: CGPoint(x: -imageSize.width - 2.0, y: 0.0), size: imageSize) + titleHorizontalOffset = imageSize.width + 2.0 + lockIconLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: imageSize) } else { lockIconLayer.contents = nil - horizontalOffset = 0.0 + titleHorizontalOffset = 0.0 } } else { if let lockIconLayer = self.lockIconLayer { self.lockIconLayer = nil lockIconLayer.removeFromSuperlayer() } - horizontalOffset = 0.0 + titleHorizontalOffset = 0.0 } - if let currentTextLayout = self.currentTextLayout, currentTextLayout.string == title, currentTextLayout.color == color, currentTextLayout.constrainedWidth == constrainedWidth { - return (currentTextLayout.size, horizontalOffset) + let textConstrainedWidth = constrainedWidth - titleHorizontalOffset - 10.0 + + let textSize: CGSize + if let currentTextLayout = self.currentTextLayout, currentTextLayout.string == title, currentTextLayout.color == color, currentTextLayout.constrainedWidth == textConstrainedWidth { + textSize = currentTextLayout.size + } else { + let string = NSAttributedString(string: title.uppercased(), font: Font.medium(12.0), 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 string = NSAttributedString(string: title.uppercased(), font: Font.medium(12.0), textColor: color) - let stringBounds = string.boundingRect(with: CGSize(width: constrainedWidth, height: 100.0), options: .usesLineFragmentOrigin, context: nil) - let size = CGSize(width: ceil(stringBounds.width), height: ceil(stringBounds.height)) - self.contents = generateImage(size, 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, constrainedWidth, size) + self.textLayer.frame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: 0.0), size: textSize) - return (size, horizontalOffset) + var clearWidth: CGFloat = 0.0 + if hasClear { + let clearIconLayer: SimpleLayer + var updateImage = themeUpdated + if let current = self.clearIconLayer { + clearIconLayer = current + } else { + updateImage = true + clearIconLayer = SimpleLayer() + self.clearIconLayer = clearIconLayer + self.addSublayer(clearIconLayer) + } + var clearSize = clearIconLayer.bounds.size + if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme) { + clearSize = image.size + clearSize.width = 10.0 + clearSize.height = 10.0 + clearIconLayer.contents = image.cgImage + } + + clearIconLayer.frame = CGRect(origin: CGPoint(x: titleHorizontalOffset + textSize.width + 4.0, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize) + clearWidth = 4.0 + clearSize.width + } + + return CGSize(width: titleHorizontalOffset + textSize.width + clearWidth, height: textSize.height) } } @@ -129,7 +213,8 @@ public final class EmojiPagerContentComponent: Component { public let performItemAction: (Item, UIView, CGRect, CALayer) -> Void public let deleteBackwards: () -> Void public let openStickerSettings: () -> Void - public let openPremiumSection: () -> 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 @@ -141,7 +226,8 @@ public final class EmojiPagerContentComponent: Component { performItemAction: @escaping (Item, UIView, CGRect, CALayer) -> Void, deleteBackwards: @escaping () -> Void, openStickerSettings: @escaping () -> Void, - openPremiumSection: @escaping () -> Void, + addGroupAction: @escaping (AnyHashable, Bool) -> Void, + clearGroup: @escaping (AnyHashable) -> Void, pushController: @escaping (ViewController) -> Void, presentController: @escaping (ViewController) -> Void, presentGlobalOverlayController: @escaping (ViewController) -> Void, @@ -152,7 +238,8 @@ public final class EmojiPagerContentComponent: Component { self.performItemAction = performItemAction self.deleteBackwards = deleteBackwards self.openStickerSettings = openStickerSettings - self.openPremiumSection = openPremiumSection + self.addGroupAction = addGroupAction + self.clearGroup = clearGroup self.pushController = pushController self.presentController = presentController self.presentGlobalOverlayController = presentGlobalOverlayController @@ -210,7 +297,9 @@ public final class EmojiPagerContentComponent: Component { public let supergroupId: AnyHashable public let groupId: AnyHashable public let title: String? - public let isPremium: Bool + public let isFeatured: Bool + public let isPremiumLocked: Bool + public let hasClear: Bool public let displayPremiumBadges: Bool public let items: [Item] @@ -218,19 +307,26 @@ public final class EmojiPagerContentComponent: Component { supergroupId: AnyHashable, groupId: AnyHashable, title: String?, - isPremium: Bool, + isFeatured: Bool, + isPremiumLocked: Bool, + hasClear: Bool, displayPremiumBadges: Bool, items: [Item] ) { self.supergroupId = supergroupId self.groupId = groupId self.title = title - self.isPremium = isPremium + self.isFeatured = isFeatured + self.isPremiumLocked = isPremiumLocked + self.hasClear = hasClear 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 } @@ -240,7 +336,13 @@ public final class EmojiPagerContentComponent: Component { if lhs.title != rhs.title { return false } - if lhs.isPremium != rhs.isPremium { + if lhs.isFeatured != rhs.isFeatured { + return false + } + if lhs.isPremiumLocked != rhs.isPremiumLocked { + return false + } + if lhs.hasClear != rhs.hasClear { return false } if lhs.displayPremiumBadges != rhs.displayPremiumBadges { @@ -323,7 +425,8 @@ public final class EmojiPagerContentComponent: Component { let supergroupId: AnyHashable let groupId: AnyHashable let hasTitle: Bool - let isPremium: Bool + let isPremiumLocked: Bool + let isFeatured: Bool let itemCount: Int } @@ -392,7 +495,7 @@ public final class EmojiPagerContentComponent: Component { let numRowsInGroup = (itemGroup.itemCount + (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.isPremium { + if itemGroup.isPremiumLocked || itemGroup.isFeatured { groupContentSize.height += self.premiumButtonInset + self.premiumButtonHeight } self.itemGroupLayouts.append(ItemGroupLayout( @@ -426,8 +529,8 @@ public final class EmojiPagerContentComponent: Component { ) } - func visibleItems(for rect: CGRect) -> [(supergroupId: AnyHashable, groupId: AnyHashable, groupIndex: Int, groupItems: Range)] { - var result: [(supergroupId: AnyHashable, groupId: AnyHashable, groupIndex: Int, groupItems: Range)] = [] + 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] @@ -443,14 +546,12 @@ public final class EmojiPagerContentComponent: Component { let minVisibleIndex = minVisibleRow * self.itemsPerRow let maxVisibleIndex = min(group.itemCount - 1, (maxVisibleRow + 1) * self.itemsPerRow - 1) - if maxVisibleIndex >= minVisibleIndex { - result.append(( - supergroupId: group.supergroupId, - groupId: group.groupId, - groupIndex: groupIndex, - groupItems: minVisibleIndex ..< (maxVisibleIndex + 1) - )) - } + result.append(( + supergroupId: group.supergroupId, + groupId: group.groupId, + groupIndex: groupIndex, + groupItems: maxVisibleIndex >= minVisibleIndex ? (minVisibleIndex ..< (maxVisibleIndex + 1)) : nil + )) } return result @@ -518,6 +619,12 @@ public final class EmojiPagerContentComponent: Component { var staticEmoji: String? } + enum Badge { + case premium + case locked + case featured + } + let item: Item private let file: TelegramMediaFile? @@ -528,6 +635,9 @@ public final class EmojiPagerContentComponent: Component { 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 { @@ -549,7 +659,6 @@ public final class EmojiPagerContentComponent: Component { renderer: MultiAnimationRenderer, placeholderColor: UIColor, blurredBadgeColor: UIColor, - displayPremiumBadgeIfAvailable: Bool, pointSize: CGSize, onUpdateDisplayPlaceholder: @escaping (Bool, Double) -> Void ) { @@ -640,20 +749,11 @@ public final class EmojiPagerContentComponent: Component { self.fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: isSmall)).start() } - - if displayPremiumBadgeIfAvailable && file.isPremiumSticker { - let premiumBadgeView = PremiumBadgeView() - let badgeSize = CGSize(width: 20.0, height: 20.0) - premiumBadgeView.frame = CGRect(origin: CGPoint(x: pointSize.width - badgeSize.width, y: pointSize.height - badgeSize.height), size: badgeSize) - premiumBadgeView.update(backgroundColor: blurredBadgeColor, size: badgeSize) - self.premiumBadgeView = premiumBadgeView - self.addSublayer(premiumBadgeView.layer) - } } 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.3 + let preScaleFactor: CGFloat = 2.0 let scaledSize = CGSize(width: floor(size.width * preScaleFactor), height: floor(size.height * preScaleFactor)) let scaleFactor = scaledSize.width / size.width @@ -705,6 +805,42 @@ public final class EmojiPagerContentComponent: Component { 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 @@ -772,7 +908,7 @@ public final class EmojiPagerContentComponent: Component { private weak var state: EmptyComponentState? private var pagerEnvironment: PagerComponentChildEnvironment? private var theme: PresentationTheme? - private var activeItemUpdated: ActionSlot<(AnyHashable, Transition)>? + private var activeItemUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)>? private var itemLayout: ItemLayout? private var peekRecognizer: PeekControllerGestureRecognizer? @@ -985,7 +1121,7 @@ public final class EmojiPagerContentComponent: Component { } public func scrollToItemGroup(id supergroupId: AnyHashable, subgroupId: Int32?) { - guard let component = self.component, let itemLayout = self.itemLayout else { + guard let component = self.component, let pagerEnvironment = self.pagerEnvironment, let itemLayout = self.itemLayout else { return } for groupIndex in 0 ..< itemLayout.itemGroupLayouts.count { @@ -1009,7 +1145,6 @@ public final class EmojiPagerContentComponent: Component { let wasIgnoringScrollingEvents = self.ignoreScrolling self.ignoreScrolling = true self.scrollView.setContentOffset(self.scrollView.contentOffset, animated: false) - self.ignoreScrolling = wasIgnoringScrollingEvents self.keepTopPanelVisibleUntilScrollingInput = true @@ -1020,7 +1155,344 @@ public final class EmojiPagerContentComponent: Component { anchorFrame = group.frame } - self.scrollView.scrollRectToVisible(CGRect(origin: anchorFrame.origin.offsetBy(dx: 0.0, dy: floor(-itemLayout.verticalGroupSpacing / 2.0) - 41.0), size: CGSize(width: 1.0, height: self.scrollView.bounds.height)), animated: true) + var scrollPosition = anchorFrame.minY + floor(-itemLayout.verticalGroupSpacing / 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: (CALayer, CGRect)] = [:] + for (id, layer) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(layer.frame) { + continue + } + previousVisibleGroupHeaders[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + } + var previousVisibleGroupBorders: [AnyHashable: (CALayer, 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)) + } + } + + 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) + + 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 layer = self.visibleGroupHeaders[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, 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 + } + } + } + + 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 (_, layer) in self.visibleGroupHeaders { + layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + } + for (id, layerAndFrame) in previousVisibleGroupHeaders { + if self.visibleGroupHeaders[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 (_, 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) + 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.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() + }) + } + } 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 (_, layer) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(layer.frame) { + continue + } + 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.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 + } + } + } + + 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 (_, layer) in self.visibleGroupHeaders { + 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 previousVisibleGroupHeaders { + if self.visibleGroupHeaders[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 (_, 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) + 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.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() + }) + } + } + } } } } @@ -1033,7 +1505,11 @@ public final class EmojiPagerContentComponent: Component { 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 _ = id + let groupHeaderPoint = self.scrollView.layer.convert(locationInScrollView, to: groupHeader) + if let clearIconLayer = groupHeader.clearIconLayer, clearIconLayer.frame.insetBy(dx: -4.0, dy: -4.0).contains(groupHeaderPoint) { + component.inputInteraction.clearGroup(id) + } + /*for group in component.itemGroups { if group.groupId == id { if group.isPremium && !self.expandedPremiumGroups.contains(id) { @@ -1180,11 +1656,12 @@ public final class EmojiPagerContentComponent: Component { } private func updateVisibleItems(transition: Transition, attemptSynchronousLoads: Bool) { - guard let component = self.component, let theme = self.theme, let itemLayout = self.itemLayout else { + guard let component = self.component, let pagerEnvironment = self.pagerEnvironment, let theme = self.theme, let itemLayout = self.itemLayout else { return } var topVisibleGroupId: AnyHashable? + var topVisibleSubgroupId: AnyHashable? var validIds = Set() var validGroupHeaderIds = Set() @@ -1192,14 +1669,16 @@ public final class EmojiPagerContentComponent: Component { var validGroupPremiumButtonIds = Set() let effectiveVisibleBounds = CGRect(origin: self.scrollView.bounds.origin, size: self.effectiveVisibleSize) - let topVisibleDetectionBounds = effectiveVisibleBounds.offsetBy(dx: 0.0, dy: 41.0) + let topVisibleDetectionBounds = effectiveVisibleBounds.offsetBy(dx: 0.0, dy: pagerEnvironment.containerInsets.top) 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 headerSize: CGSize? @@ -1216,19 +1695,21 @@ public final class EmojiPagerContentComponent: Component { self.visibleGroupHeaders[itemGroup.groupId] = groupHeaderLayer self.scrollView.layer.addSublayer(groupHeaderLayer) } - let (groupHeaderSize, groupHeaderHorizontalOffset) = groupHeaderLayer.update(theme: theme, title: title, isPremium: itemGroup.isPremium, constrainedWidth: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right - 32.0) + let groupHeaderSize = groupHeaderLayer.update(theme: theme, title: title, isPremiumLocked: itemGroup.isPremiumLocked, hasClear: itemGroup.hasClear, constrainedWidth: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right) if groupHeaderLayer.bounds.size != groupHeaderSize { headerSizeUpdated = true } - let groupHeaderFrame = CGRect(origin: CGPoint(x: groupHeaderHorizontalOffset + floor((itemLayout.contentSize.width - groupHeaderSize.width - groupHeaderHorizontalOffset) / 2.0), y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) + let groupHeaderFrame = CGRect(origin: CGPoint(x: floor((itemLayout.contentSize.width - groupHeaderSize.width) / 2.0), y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) groupHeaderLayer.bounds = CGRect(origin: CGPoint(), size: groupHeaderFrame.size) groupHeaderTransition.setPosition(layer: groupHeaderLayer, position: CGPoint(x: groupHeaderFrame.midX, y: groupHeaderFrame.midY)) - headerSize = CGSize(width: groupHeaderSize.width + groupHeaderHorizontalOffset, height: groupHeaderSize.height) + headerSize = CGSize(width: groupHeaderSize.width, height: groupHeaderSize.height) } - if itemGroup.isPremium { + let groupBorderRadius: CGFloat = 16.0 + + if itemGroup.isPremiumLocked { validGroupBorderIds.insert(itemGroup.groupId) let groupBorderLayer: GroupBorderLayer var groupBorderTransition = transition @@ -1252,8 +1733,6 @@ public final class EmojiPagerContentComponent: Component { 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)) - let radius: CGFloat = 16.0 - if groupBorderLayer.bounds.size != groupBorderFrame.size || headerSizeUpdated { let headerWidth: CGFloat if let headerSize = headerSize { @@ -1262,6 +1741,7 @@ public final class EmojiPagerContentComponent: Component { 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) @@ -1287,8 +1767,12 @@ public final class EmojiPagerContentComponent: Component { 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 { + let groupPremiumButtonMeasuringFrame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.maxY - 50.0 + 1.0), size: CGSize(width: 100.0, height: 50.0)) - if itemGroup.isPremium { + if effectiveVisibleBounds.intersects(groupPremiumButtonMeasuringFrame) { validGroupPremiumButtonIds.insert(itemGroup.groupId) let groupPremiumButton: ComponentView @@ -1301,34 +1785,59 @@ public final class EmojiPagerContentComponent: Component { self.visibleGroupPremiumButtons[itemGroup.groupId] = groupPremiumButton } + let groupId = itemGroup.groupId + let isPremiumLocked = itemGroup.isPremiumLocked + //TODO:localize + let title: String + let backgroundColor: UIColor + let backgroundColors: [UIColor] + let foregroundColor: UIColor + let animationName: String? + let gloss: Bool + if itemGroup.isPremiumLocked { + title = "Unlock \(itemGroup.title ?? "Emoji")" + 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 = "Add \(itemGroup.title ?? "Emoji")" + backgroundColors = [] + backgroundColor = theme.list.itemCheckColors.fillColor + foregroundColor = theme.list.itemCheckColors.foregroundColor + animationName = nil + gloss = false + } + let groupPremiumButtonSize = groupPremiumButton.update( transition: groupPremiumButtonTransition, component: AnyComponent(SolidRoundedButtonComponent( - title: "Unlock \(itemGroup.title ?? "Emoji")", + title: title, theme: SolidRoundedButtonComponent.Theme( - backgroundColor: .black, - backgroundColors: [ - UIColor(rgb: 0x0077ff), - UIColor(rgb: 0x6b93ff), - UIColor(rgb: 0x8878ff), - UIColor(rgb: 0xe46ace) - ], - foregroundColor: .white + backgroundColor: backgroundColor, + backgroundColors: backgroundColors, + foregroundColor: foregroundColor ), font: .bold, fontSize: 17.0, height: 50.0, - cornerRadius: radius, - gloss: true, - animationName: "premium_unlock", + 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.inputInteraction.openPremiumSection() + component.inputInteraction.addGroupAction(groupId, isPremiumLocked) } )), environment: {}, @@ -1351,114 +1860,128 @@ public final class EmojiPagerContentComponent: Component { } } - for index in groupItems.groupItems.lowerBound ..< groupItems.groupItems.upperBound { - let item = itemGroup.items[index] - 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.fitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) - let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) - - var updateItemLayerPlaceholder = false - var itemTransition = transition - let itemLayer: ItemLayer - if let current = self.visibleItemLayers[itemId] { - itemLayer = current - } else { - updateItemLayerPlaceholder = true - itemTransition = .immediate + if let groupItemRange = groupItems.groupItems { + for index in groupItemRange.lowerBound ..< groupItemRange.upperBound { + let item = itemGroup.items[index] - itemLayer = ItemLayer( - item: item, - context: component.context, - attemptSynchronousLoad: attemptSynchronousLoads, - file: item.file, - staticEmoji: item.staticEmoji, - cache: component.animationCache, - renderer: component.animationRenderer, - placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), - blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), - displayPremiumBadgeIfAvailable: itemGroup.displayPremiumBadges, - pointSize: itemNativeFitSize, - 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: nil, - size: itemNativeFitSize - ) - strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView - strongSelf.placeholdersContainerView.addSubview(placeholderView) - } - placeholderView.frame = itemLayer.frame - placeholderView.update(size: placeholderView.bounds.size) - - strongSelf.updateShimmerIfNeeded() + 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.fitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) + let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) + + var updateItemLayerPlaceholder = false + var itemTransition = transition + let itemLayer: ItemLayer + if let current = self.visibleItemLayers[itemId] { + itemLayer = current + } else { + updateItemLayerPlaceholder = true + itemTransition = .immediate + + itemLayer = ItemLayer( + item: item, + context: component.context, + attemptSynchronousLoad: attemptSynchronousLoads, + file: item.file, + staticEmoji: item.staticEmoji, + cache: component.animationCache, + renderer: component.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 } - } 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() + 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: nil, + 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 itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY) + let itemBounds = CGRect(origin: CGPoint(), size: itemFrame.size) + itemTransition.setPosition(layer: itemLayer, position: itemPosition) + itemTransition.setBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + + 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: 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) } - ) - 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 itemPosition = CGPoint(x: itemFrame.midX, y: itemFrame.midY) - let itemBounds = CGRect(origin: CGPoint(), size: itemFrame.size) - itemTransition.setPosition(layer: itemLayer, position: itemPosition) - itemTransition.setBounds(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.setFrame(view: placeholderView, frame: itemFrame) - placeholderView.update(size: itemFrame.size) - } - } else if updateItemLayerPlaceholder { - if itemLayer.displayPlaceholder { - itemLayer.onUpdateDisplayPlaceholder(true, 0.0) } + + itemLayer.isVisibleForAnimations = true } - - itemLayer.isVisibleForAnimations = true } } @@ -1517,7 +2040,7 @@ public final class EmojiPagerContentComponent: Component { } if let topVisibleGroupId = topVisibleGroupId { - self.activeItemUpdated?.invoke((topVisibleGroupId, .immediate)) + self.activeItemUpdated?.invoke((topVisibleGroupId, topVisibleSubgroupId, .immediate)) } } @@ -1530,6 +2053,8 @@ public final class EmojiPagerContentComponent: Component { } func update(component: EmojiPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let previousComponent = self.component + self.component = component self.state = state @@ -1549,13 +2074,37 @@ public final class EmojiPagerContentComponent: Component { let shimmerForegroundColor = keyboardChildEnvironment.theme.list.itemBlocksBackgroundColor.withMultipliedAlpha(0.15) self.standaloneShimmerEffect.update(background: shimmerBackgroundColor, foreground: shimmerForegroundColor) + var anchorItem: (key: ItemLayer.Key, frame: CGRect)? + if let previousComponent = previousComponent, previousComponent.itemGroups != component.itemGroups { + 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, - isPremium: itemGroup.isPremium, + isPremiumLocked: itemGroup.isPremiumLocked, + isFeatured: itemGroup.isFeatured, itemCount: itemGroup.items.count )) } @@ -1602,6 +2151,40 @@ public final class EmojiPagerContentComponent: Component { 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 + } + self.scrollView.setContentOffset(CGPoint(x: 0.0, y: contentOffsetY), animated: false) + + break outer + } + } + } + } + self.ignoreScrolling = false self.updateVisibleItems(transition: itemTransition, attemptSynchronousLoads: !(scrollView.isDragging || scrollView.isDecelerating)) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 75011510bb..b86a6fdaad 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -13,11 +13,11 @@ import SwiftSignalKit public final class EntityKeyboardChildEnvironment: Equatable { public let theme: PresentationTheme - public let getContentActiveItemUpdated: (AnyHashable) -> ActionSlot<(AnyHashable, Transition)>? + public let getContentActiveItemUpdated: (AnyHashable) -> ActionSlot<(AnyHashable, AnyHashable?, Transition)>? public init( theme: PresentationTheme, - getContentActiveItemUpdated: @escaping (AnyHashable) -> ActionSlot<(AnyHashable, Transition)>? + getContentActiveItemUpdated: @escaping (AnyHashable) -> ActionSlot<(AnyHashable, AnyHashable?, Transition)>? ) { self.theme = theme self.getContentActiveItemUpdated = getContentActiveItemUpdated @@ -200,8 +200,8 @@ public final class EntityKeyboardComponent: Component { var contentAccessoryLeftButtons: [AnyComponentWithIdentity] = [] var contentAccessoryRightButtons: [AnyComponentWithIdentity] = [] - let gifsContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() - let stickersContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() + let gifsContentItemIdUpdated = ActionSlot<(AnyHashable, AnyHashable?, Transition)>() + let stickersContentItemIdUpdated = ActionSlot<(AnyHashable, AnyHashable?, Transition)>() if transition.userData(MarkInputCollapsed.self) != nil { self.searchComponent = nil @@ -242,6 +242,8 @@ public final class EntityKeyboardComponent: Component { 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, @@ -293,8 +295,9 @@ public final class EntityKeyboardComponent: Component { let iconMapping: [String: String] = [ "saved": "Chat/Input/Media/SavedStickersTabIcon", "recent": "Chat/Input/Media/RecentTabIcon", - "premium": "Chat/Input/Media/PremiumIcon" + "premium": "Peer Info/PremiumIcon" ] + //TODO:localize let titleMapping: [String: String] = [ "saved": "Saved", "recent": "Recent", @@ -323,6 +326,8 @@ public final class EntityKeyboardComponent: Component { content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( context: stickerContent.context, file: file, + isFeatured: itemGroup.isFeatured, + isPremiumLocked: itemGroup.isPremiumLocked, animationCache: stickerContent.animationCache, animationRenderer: stickerContent.animationRenderer, theme: component.theme, @@ -375,18 +380,42 @@ public final class EntityKeyboardComponent: Component { ).minSize(CGSize(width: 38.0, height: 38.0))))) } - let emojiContentItemIdUpdated = ActionSlot<(AnyHashable, Transition)>() + 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 == "static" { + if id == "recent" { + let iconMapping: [String: String] = [ + "recent": "Chat/Input/Media/RecentTabIcon", + ] + //TODO:localize + let titleMapping: [String: String] = [ + "recent": "Recent", + ] + if let iconName = iconMapping[id], let title = titleMapping[id] { + topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( + id: itemGroup.supergroupId, + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: iconName, + theme: component.theme, + title: title, + pressed: { [weak self] in + self?.scrollToItemGroup(contentId: "emoji", groupId: itemGroup.supergroupId, subgroupId: nil) + } + )) + )) + } + } else if id == "static" { + //TODO:localize topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.supergroupId, isReorderable: false, content: AnyComponent(EntityKeyboardStaticStickersPanelComponent( theme: component.theme, + title: "Emoji", pressed: { [weak self] subgroupId in guard let strongSelf = self else { return @@ -404,6 +433,8 @@ public final class EntityKeyboardComponent: Component { 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, @@ -651,9 +682,17 @@ public final class EntityKeyboardComponent: Component { } private func scrollToItemGroup(contentId: String, groupId: AnyHashable, subgroupId: Int32?) { - if let pagerView = self.pagerView.findTaggedView(tag: EmojiPagerContentComponent.Tag(id: contentId)) as? EmojiPagerContentComponent.View { - pagerView.scrollToItemGroup(id: groupId, subgroupId: subgroupId) + 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]) { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift index 54bacc37aa..7057727731 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -91,8 +91,6 @@ final class EntityKeyboardTopContainerPanelComponent: Component { let intrinsicHeight: CGFloat = 41.0 let height = intrinsicHeight - let isExpanded = availableSize.height > 41.0 - let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value var transitionOffsetFraction: CGFloat = 0.0 @@ -142,10 +140,6 @@ final class EntityKeyboardTopContainerPanelComponent: Component { self.addSubview(panelView.view) } - if !isExpanded { - panelView.isExpanded = false - } - let panelId = panel.id let _ = panelView.view.update( transition: panelTransition, @@ -261,6 +255,12 @@ final class EntityKeyboardTopContainerPanelComponent: Component { 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 diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 7e2fe8382a..ab8c7057d8 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -18,6 +18,8 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { let context: AccountContext let file: TelegramMediaFile + let isFeatured: Bool + let isPremiumLocked: Bool let animationCache: AnimationCache let animationRenderer: MultiAnimationRenderer let theme: PresentationTheme @@ -27,6 +29,8 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { init( context: AccountContext, file: TelegramMediaFile, + isFeatured: Bool, + isPremiumLocked: Bool, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, theme: PresentationTheme, @@ -35,6 +39,8 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { ) { self.context = context self.file = file + self.isFeatured = isFeatured + self.isPremiumLocked = isPremiumLocked self.animationCache = animationCache self.animationRenderer = animationRenderer self.theme = theme @@ -49,6 +55,12 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { 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 } @@ -107,7 +119,6 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { renderer: component.animationRenderer, placeholderColor: .lightGray, blurredBadgeColor: .clear, - displayPremiumBadgeIfAvailable: false, pointSize: CGSize(width: 44.0, height: 44.0), onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { @@ -130,6 +141,15 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { 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 } @@ -144,7 +164,8 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { 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)) + 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) @@ -154,7 +175,7 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { 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), size: titleSize) + 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 { @@ -274,12 +295,35 @@ final class EntityKeyboardIconTopPanelComponent: Component { if self.component?.imageName != component.imageName { self.iconView.image = generateTintedImage(image: UIImage(bundleImageName: component.imageName), color: component.theme.chat.inputMediaPanel.panelIconColor) + + if component.imageName.hasSuffix("PremiumIcon") { + self.iconView.image = generateImage(CGSize(width: 44.0, height: 42.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + if let image = UIImage(bundleImageName: "Peer Info/PremiumIcon") { + 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.component = component let nativeIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 28.0, height: 28.0) - let boundingIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 38.0, height: 38.0) : CGSize(width: 24.0, height: 24.0) + let boundingIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 38.0, height: 38.0) : CGSize(width: 28.0, height: 28.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) @@ -297,7 +341,8 @@ final class EntityKeyboardIconTopPanelComponent: Component { 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)) + 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) @@ -307,7 +352,7 @@ final class EntityKeyboardIconTopPanelComponent: Component { 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), size: titleSize) + 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 { @@ -336,13 +381,16 @@ 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 } @@ -350,19 +398,29 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { if lhs.theme !== rhs.theme { return false } + if lhs.title != rhs.title { + return false + } return true } final class View: UIView, UIScrollViewDelegate { + 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 ignoreScrolling: Bool = false override init(frame: CGRect) { + self.scrollViewContainer = UIView() + self.scrollViewContainer.clipsToBounds = true + self.scrollView = UIScrollView() super.init(frame: frame) @@ -380,9 +438,9 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.alwaysBounceHorizontal = false self.scrollView.delegate = self - self.addSubview(self.scrollView) - self.clipsToBounds = true + self.scrollViewContainer.addSubview(self.scrollView) + self.addSubview(self.scrollViewContainer) self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.tapGesture(_:)))) } @@ -411,31 +469,36 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { } private func updateVisibleItems(transition: Transition, animateAppearingItems: Bool) { - guard let component = self.component else { + guard let component = self.component, let itemEnvironment = self.itemEnvironment else { return } - let _ = component - var validItemIds = Set() let visibleBounds = self.scrollView.bounds - let componentHeight: CGFloat = 32.0 + let componentHeight: CGFloat = self.scrollView.contentSize.height + + let isExpanded = componentHeight > 32.0 let items = EmojiPagerContentComponent.StaticEmojiSegment.allCases - let itemSize: CGFloat = 28.0 + let itemSize: CGFloat = isExpanded ? 42.0 : 32.0 let itemSpacing: CGFloat = 4.0 - let sideInset: CGFloat = 2.0 + let sideInset: CGFloat = isExpanded ? 5.0 : 2.0 + let itemOffset: CGFloat = isExpanded ? -8.0 : 0.0 for i in 0 ..< items.count { - let itemFrame = CGRect(origin: CGPoint(x: sideInset + CGFloat(i) * (itemSize + itemSpacing), y: floor(componentHeight - itemSize) / 2.0), size: CGSize(width: itemSize, height: itemSize)) + let itemFrame = CGRect(origin: CGPoint(x: sideInset + CGFloat(i) * (itemSize + itemSpacing), y: floor(componentHeight - itemSize) / 2.0 + itemOffset), size: CGSize(width: itemSize, height: itemSize)) if 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 } @@ -460,14 +523,21 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { animationName = "emojicat_flags" } + let color: UIColor + if itemEnvironment.highlightedSubgroupId == AnyHashable(items[i].rawValue) { + color = component.theme.chat.inputMediaPanel.panelIconColor.mixedWith(component.theme.chat.inputPanel.primaryTextColor, alpha: 0.35) + } else { + color = component.theme.chat.inputMediaPanel.panelIconColor + } + let _ = itemView.update( - transition: .immediate, + transition: itemTransition, component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: animationName, - colors: ["__allcolors__": component.theme.chat.inputMediaPanel.panelIconColor], - mode: animateAppearingItems ? .animating(loop: false) : .still(position: .end) + mode: animateItem ? .animating(loop: false) : .still(position: .end) ), + colors: ["__allcolors__": color], size: CGSize(width: itemSize, height: itemSize) )), environment: {}, @@ -477,7 +547,7 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { if view.superview == nil { self.scrollView.addSubview(view) } - view.frame = itemFrame + itemTransition.setFrame(view: view, frame: itemFrame) } } } @@ -495,26 +565,80 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { } func update(component: EntityKeyboardStaticStickersPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { - self.layer.cornerRadius = availableSize.height / 2.0 + transition.setFrame(view: self.scrollViewContainer, frame: CGRect(origin: CGPoint(), size: availableSize)) + transition.setCornerRadius(layer: self.scrollViewContainer.layer, cornerRadius: min(availableSize.width / 2.0, availableSize.height / 2.0)) let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value - self.component = component + var scrollToItem: AnyHashable? + if itemEnvironment.highlightedSubgroupId != self.itemEnvironment?.highlightedSubgroupId { + scrollToItem = itemEnvironment.highlightedSubgroupId + } - let itemSize: CGFloat = 28.0 + self.component = component + self.itemEnvironment = itemEnvironment + + let isExpanded = itemEnvironment.isExpanded + let itemSize: CGFloat = isExpanded ? 42.0 : 32.0 let itemSpacing: CGFloat = 4.0 - let sideInset: CGFloat = 2.0 + let sideInset: CGFloat = isExpanded ? 5.0 : 2.0 let itemCount = EmojiPagerContentComponent.StaticEmojiSegment.allCases.count self.ignoreScrolling = true - self.scrollView.frame = CGRect(origin: CGPoint(), size: CGSize(width: max(availableSize.width, 150.0), height: availableSize.height)) + self.scrollView.frame = CGRect(origin: CGPoint(), size: CGSize(width: max(availableSize.width, 160.0), height: availableSize.height)) self.scrollView.contentSize = CGSize(width: sideInset * 2.0 + itemSize * CGFloat(itemCount) + itemSpacing * CGFloat(itemCount - 1), height: availableSize.height) self.ignoreScrolling = false - self.updateVisibleItems(transition: .immediate, animateAppearingItems: false) + self.updateVisibleItems(transition: transition, animateAppearingItems: false) - if !itemEnvironment.isHighlighted && self.scrollView.contentOffset.x != 0.0 { + if (!itemEnvironment.isHighlighted || isExpanded) && self.scrollView.contentOffset.x != 0.0 { self.scrollView.setContentOffset(CGPoint(), animated: true) + scrollToItem = nil + } + + if let scrollToItem = scrollToItem { + let items = EmojiPagerContentComponent.StaticEmojiSegment.allCases + for i in 0 ..< items.count { + if AnyHashable(items[i].rawValue) == scrollToItem { + let itemFrame = CGRect(origin: CGPoint(x: sideInset + CGFloat(i) * (itemSize + itemSpacing), y: 0.0), size: CGSize(width: itemSize, height: itemSize)) + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -sideInset, 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 { + transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in + view?.removeFromSuperview() + }) + } } return availableSize @@ -533,10 +657,12 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { final class EntityKeyboardTopPanelItemEnvironment: Equatable { let isExpanded: Bool let isHighlighted: Bool + let highlightedSubgroupId: AnyHashable? - init(isExpanded: Bool, isHighlighted: Bool) { + init(isExpanded: Bool, isHighlighted: Bool, highlightedSubgroupId: AnyHashable?) { self.isExpanded = isExpanded self.isHighlighted = isHighlighted + self.highlightedSubgroupId = highlightedSubgroupId } static func ==(lhs: EntityKeyboardTopPanelItemEnvironment, rhs: EntityKeyboardTopPanelItemEnvironment) -> Bool { @@ -546,6 +672,9 @@ final class EntityKeyboardTopPanelItemEnvironment: Equatable { if lhs.isHighlighted != rhs.isHighlighted { return false } + if lhs.highlightedSubgroupId != rhs.highlightedSubgroupId { + return false + } return true } } @@ -617,6 +746,8 @@ private final class ReorderGestureRecognizer: UIGestureRecognizer { self.stopLongTapTimer() self.stopLongPressTimer() self.initialLocation = nil + + self.isActiveUpdated(false) } private func longTapTimerFired() { @@ -776,14 +907,14 @@ final class EntityKeyboardTopPanelComponent: Component { let theme: PresentationTheme let items: [Item] let defaultActiveItemId: AnyHashable? - let activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)> + let activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)> let reorderItems: ([Item]) -> Void init( theme: PresentationTheme, items: [Item], defaultActiveItemId: AnyHashable? = nil, - activeContentItemIdUpdated: ActionSlot<(AnyHashable, Transition)>, + activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)>, reorderItems: @escaping ([Item]) -> Void ) { self.theme = theme @@ -836,7 +967,7 @@ final class EntityKeyboardTopPanelComponent: Component { self.isExpanded = isExpanded self.itemSize = self.isExpanded ? CGSize(width: 54.0, height: 68.0) : CGSize(width: 32.0, height: 32.0) self.staticItemSize = self.itemSize - self.staticExpandedItemSize = self.isExpanded ? CGSize(width: 150.0, height: 68.0) : CGSize(width: 150.0, height: 32.0) + self.staticExpandedItemSize = self.isExpanded ? self.staticItemSize : CGSize(width: 160.0, height: 32.0) self.innerItemSize = self.isExpanded ? CGSize(width: 50.0, height: 62.0) : CGSize(width: 28.0, height: 28.0) var contentSize = CGSize(width: sideInset, height: height) @@ -887,11 +1018,19 @@ final class EntityKeyboardTopPanelComponent: Component { return self.items[index].frame } - func contentFrame(containerFrame: CGRect) -> CGRect { + 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 += floor((self.itemSize.width - self.innerItemSize.width)) / 2.0 - frame.origin.y += floor((self.itemSize.height - self.innerItemSize.height)) / 2.0 - frame.size = self.innerItemSize + frame.origin.x -= offsetDifference.x + frame.origin.y -= offsetDifference.y + frame.size.width -= sizeDifference.width + frame.size.height -= sizeDifference.height + return frame } @@ -933,12 +1072,17 @@ final class EntityKeyboardTopPanelComponent: Component { 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? @@ -980,7 +1124,7 @@ final class EntityKeyboardTopPanelComponent: Component { return strongSelf.scrollView.contentOffset.x > 0.0 } - self.addGestureRecognizer(ReorderGestureRecognizer( + let reorderGestureRecognizer = ReorderGestureRecognizer( shouldBegin: { [weak self] point in guard let strongSelf = self else { return (false, false, nil) @@ -1022,7 +1166,9 @@ final class EntityKeyboardTopPanelComponent: Component { } strongSelf.updateIsReordering(isActive) } - )) + ) + self.reorderGestureRecognizer = reorderGestureRecognizer + self.addGestureRecognizer(reorderGestureRecognizer) } required init?(coder: NSCoder) { @@ -1038,10 +1184,60 @@ final class EntityKeyboardTopPanelComponent: Component { } 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) } @@ -1187,7 +1383,8 @@ final class EntityKeyboardTopPanelComponent: Component { } var visibleBounds = self.scrollView.bounds - visibleBounds.size.width += 200.0 + visibleBounds.origin.x -= 200.0 + visibleBounds.size.width += 400.0 var validIds = Set() let visibleItemRange = itemLayout.visibleItemRange(for: visibleBounds) @@ -1212,7 +1409,7 @@ final class EntityKeyboardTopPanelComponent: Component { transition: itemTransition, component: item.content, environment: { - EntityKeyboardTopPanelItemEnvironment(isExpanded: itemLayout.isExpanded, isHighlighted: self.activeContentItemId == item.id) + EntityKeyboardTopPanelItemEnvironment(isExpanded: itemLayout.isExpanded, isHighlighted: self.activeContentItemId == item.id, highlightedSubgroupId: self.activeContentItemId == item.id ? self.activeSubcontentItemId : nil) }, containerSize: itemOuterFrame.size ) @@ -1259,6 +1456,7 @@ final class EntityKeyboardTopPanelComponent: Component { } if self.isReordering { self.isReordering = false + self.reorderGestureRecognizer?.state = .failed } if self.isDraggingOrReordering { self.isDraggingOrReordering = false @@ -1302,35 +1500,124 @@ final class EntityKeyboardTopPanelComponent: Component { 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.size.width += 200.0 + visibleBounds.origin.x -= 200.0 + visibleBounds.size.width += 400.0 let previousVisibleRange = previousItemLayout.visibleItemRange(for: visibleBounds) if previousVisibleRange.minIndex <= previousVisibleRange.maxIndex { - let previousItemFrame = previousItemLayout.containerFrame(at: previousVisibleRange.minIndex) - let updatedItemFrame = itemLayout.containerFrame(at: previousVisibleRange.minIndex) + 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 - let previousDistanceToItem = (previousItemFrame.minX - self.scrollView.bounds.minX)// / previousItemFrame.width - let newBounds = CGRect(origin: CGPoint(x: updatedItemFrame.minX - previousDistanceToItem/* * updatedItemFrame.width)*/, y: 0.0), size: availableSize) updatedBounds = newBounds var updatedVisibleBounds = newBounds - updatedVisibleBounds.size.width += 200.0 + updatedVisibleBounds.origin.x -= 200.0 + updatedVisibleBounds.size.width += 400.0 let updatedVisibleRange = itemLayout.visibleItemRange(for: updatedVisibleBounds) - let baseFrame = CGRect(origin: CGPoint(x: updatedItemFrame.minX, y: previousItemFrame.minY), size: previousItemFrame.size) - for index in updatedVisibleRange.minIndex ..< updatedVisibleRange.maxIndex { - let indexDifference = index - previousVisibleRange.minIndex - if let itemView = self.itemViews[self.items[index].id] { - let itemContainerOriginX = baseFrame.minX + CGFloat(indexDifference) * (previousItemLayout.itemSize.width + previousItemLayout.itemSpacing) - let itemContainerFrame = CGRect(origin: CGPoint(x: itemContainerOriginX, y: baseFrame.minY), size: baseFrame.size) - let itemOuterFrame = previousItemLayout.contentFrame(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 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 { @@ -1355,7 +1642,13 @@ final class EntityKeyboardTopPanelComponent: Component { highlightTransition = .immediate } - highlightTransition.setCornerRadius(layer: self.highlightedIconBackgroundView.layer, cornerRadius: activeContentItemId.base is String ? min(itemFrame.width / 2.0, itemFrame.height / 2.0) : 10.0) + let isRound: Bool + if let string = activeContentItemId.base as? String, (string == "recent" || string == "static") { + 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 { @@ -1373,11 +1666,11 @@ final class EntityKeyboardTopPanelComponent: Component { strongSelf.visibilityFractionUpdated(value: fraction, transition: transition) } - component.activeContentItemIdUpdated.connect { [weak self] (itemId, transition) in + component.activeContentItemIdUpdated.connect { [weak self] (itemId, subcontentItemId, transition) in guard let strongSelf = self else { return } - strongSelf.activeContentItemIdUpdated(itemId: itemId, transition: transition) + strongSelf.activeContentItemIdUpdated(itemId: itemId, subcontentItemId: subcontentItemId, transition: transition) } return CGSize(width: availableSize.width, height: height) @@ -1401,14 +1694,15 @@ final class EntityKeyboardTopPanelComponent: Component { } } - private func activeContentItemIdUpdated(itemId: AnyHashable, transition: Transition) { + private func activeContentItemIdUpdated(itemId: AnyHashable, subcontentItemId: AnyHashable?, transition: Transition) { guard let component = self.component, let itemLayout = self.itemLayout else { return } - if self.activeContentItemId == itemId { + if self.activeContentItemId == itemId && self.activeSubcontentItemId == subcontentItemId { return } self.activeContentItemId = itemId + self.activeSubcontentItemId = subcontentItemId let _ = component let _ = itemLayout diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index d0caa97fcf..3ff0d8f0f8 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -42,12 +42,14 @@ private class GifVideoLayer: AVSampleBufferDisplayLayer { 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 } - strongSelf.frameManager?.tick(timestamp: strongSelf.playbackTimestamp) - strongSelf.playbackTimestamp += 1.0 / 30.0 + let timestamp = CFAbsoluteTimeGetCurrent() - startTimestamp + strongSelf.frameManager?.tick(timestamp: timestamp) + strongSelf.playbackTimestamp = timestamp }, queue: .mainQueue()) self.playbackTimer?.start() } else { @@ -560,7 +562,7 @@ public final class GifPagerContentComponent: Component { } private func updateScrollingOffset(transition: Transition) { - let isInteracting = scrollView.isDragging || scrollView.isTracking || scrollView.isDecelerating + let isInteracting = scrollView.isDragging || scrollView.isDecelerating if let previousScrollingOffsetValue = self.previousScrollingOffset { let currentBounds = scrollView.bounds let offsetToTopEdge = max(0.0, currentBounds.minY - 0.0) diff --git a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift index 9cac2ad1a3..bc09070b5b 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift +++ b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift @@ -14,14 +14,27 @@ public func cacheLottieAnimation(data: Data, width: Int, height: Int, writer: An return } - let frameDuration = 1.0 / Double(animation.frameRate) - for i in 0 ..< animation.frameCount { + + let frameSkip: Int + if animation.frameRate >= 60 { + if ProcessInfo.processInfo.activeProcessorCount > 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)) - }, proposedWidth: width, proposedHeight: height, duration: frameDuration) + return frameDuration + }, proposedWidth: width, proposedHeight: height) } writer.finish() @@ -39,7 +52,8 @@ public func cacheStillSticker(path: String, width: Int, height: Int, writer: Ani UIGraphicsPopContext() } memcpy(surface.argb, context.bytes, surface.height * surface.bytesPerRow) - }, proposedWidth: width, proposedHeight: height, duration: 1.0) + return 1.0 + }, proposedWidth: width, proposedHeight: height) } writer.finish() diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift index 2a1c71affb..df715c5a18 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift @@ -249,14 +249,18 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } private final class Frame { - let timestamp: Double + let duration: Double let textureY: TextureStorage let textureU: TextureStorage let textureV: TextureStorage let textureA: TextureStorage - init?(device: MTLDevice, textureY: TextureStorage, textureU: TextureStorage, textureV: TextureStorage, textureA: TextureStorage, data: AnimationCacheItemFrame, timestamp: Double) { - self.timestamp = timestamp + 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 @@ -281,7 +285,6 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { private let stateUpdated: () -> Void private var disposable: Disposable? - private var timestamp: Double = 0.0 private var item: AnimationCacheItem? private(set) var currentFrame: Frame? @@ -354,18 +357,35 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { return self.update(device: device, texturePoolFullPlane: texturePoolFullPlane, texturePoolHalfPlane: texturePoolHalfPlane, advanceTimestamp: advanceTimestamp) } - private func update(device: MTLDevice, texturePoolFullPlane: TextureStoragePool, texturePoolHalfPlane: TextureStoragePool, advanceTimestamp: Double?) -> LoadFrameTask? { + private func update(device: MTLDevice, texturePoolFullPlane: TextureStoragePool, texturePoolHalfPlane: TextureStoragePool, advanceTimestamp: Double) -> LoadFrameTask? { guard let item = self.item else { return nil } - let timestamp = self.timestamp - if let advanceTimestamp = advanceTimestamp { - self.timestamp += advanceTimestamp + if let currentFrame = self.currentFrame, !self.isLoadingFrame { + currentFrame.remainingDuration -= advanceTimestamp } - if let currentFrame = self.currentFrame, currentFrame.timestamp == self.timestamp { - } else if !self.isLoadingFrame { + 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 @@ -378,7 +398,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { let preferredRowAlignment = self.preferredRowAlignment return LoadFrameTask(task: { [weak self] in - let frame = item.getFrame(at: timestamp, requestedFormat: .yuva(rowAlignment: preferredRowAlignment)) + 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) @@ -387,7 +407,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { 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, timestamp: timestamp) + currentFrame = Frame(device: device, textureY: textureY, textureU: textureU, textureV: textureV, textureA: textureA, data: frame, duration: frame.duration) } return { diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index 08a52b35db..ffe00bae70 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -29,6 +29,17 @@ 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) @@ -65,60 +76,6 @@ open class MultiAnimationRenderTarget: SimpleLayer { } } -private final class FrameGroup { - let image: UIImage - let badgeImage: UIImage? - let size: CGSize - let timestamp: Double - - init?(item: AnimationCacheItem, timestamp: Double) { - guard let firstFrame = item.getFrame(at: timestamp, requestedFormat: .rgba) else { - return nil - } - - switch firstFrame.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) - - /*var sourceBuffer = vImage_Buffer() - sourceBuffer.width = UInt(width) - sourceBuffer.height = UInt(height) - sourceBuffer.data = UnsafeMutableRawPointer(mutating: bytes.baseAddress!.advanced(by: firstFrame.range.lowerBound)) - sourceBuffer.rowBytes = bytesPerRow - - var destinationBuffer = vImage_Buffer() - destinationBuffer.width = UInt(32) - destinationBuffer.height = UInt(32) - destinationBuffer.data = context.bytes - destinationBuffer.rowBytes = bytesPerRow - - vImageBoxConvolve_ARGB8888(&sourceBuffer, - &destinationBuffer, - nil, - UInt(width - 32 - 16), UInt(height - 32 - 16), - UInt32(31), - UInt32(31), - nil, - vImage_Flags(kvImageEdgeExtend))*/ - } - - guard let image = context.generateImage() else { - return nil - } - - self.image = image - self.size = CGSize(width: CGFloat(width), height: CGFloat(height)) - self.timestamp = timestamp - self.badgeImage = nil - default: - return nil - } - } -} - private final class LoadFrameGroupTask { let task: () -> () -> Void @@ -128,6 +85,190 @@ 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) + + /*var sourceBuffer = vImage_Buffer() + sourceBuffer.width = UInt(width) + sourceBuffer.height = UInt(height) + sourceBuffer.data = UnsafeMutableRawPointer(mutating: bytes.baseAddress!.advanced(by: firstFrame.range.lowerBound)) + sourceBuffer.rowBytes = bytesPerRow + + var destinationBuffer = vImage_Buffer() + destinationBuffer.width = UInt(32) + destinationBuffer.height = UInt(32) + destinationBuffer.data = context.bytes + destinationBuffer.rowBytes = bytesPerRow + + vImageBoxConvolve_ARGB8888(&sourceBuffer, + &destinationBuffer, + nil, + UInt(width - 32 - 16), UInt(height - 32 - 16), + UInt32(31), + UInt32(31), + nil, + vImage_Flags(kvImageEdgeExtend))*/ + } + + 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) + + 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 { + let size = CGSize(width: CGFloat(blurredWidth), height: CGFloat(blurredHeight)) + 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 + + /*var sourceBuffer = vImage_Buffer() + sourceBuffer.width = UInt(width) + sourceBuffer.height = UInt(height) + sourceBuffer.data = UnsafeMutableRawPointer(mutating: bytes.baseAddress!) + sourceBuffer.rowBytes = bytesPerRow + + let tempBufferBytes = malloc(blurredHeight * context.bytesPerRow) + defer { + free(tempBufferBytes) + } + let temp2BufferBytes = malloc(blurredHeight * context.bytesPerRow) + defer { + free(temp2BufferBytes) + } + memset(temp2BufferBytes, Int32(bitPattern: color?.argb ?? 0xffffffff), blurredHeight * context.bytesPerRow) + + var tempBuffer = vImage_Buffer() + tempBuffer.width = UInt(blurredWidth) + tempBuffer.height = UInt(blurredHeight) + tempBuffer.data = tempBufferBytes + tempBuffer.rowBytes = context.bytesPerRow + + var temp2Buffer = vImage_Buffer() + temp2Buffer.width = UInt(blurredWidth) + temp2Buffer.height = UInt(blurredHeight) + temp2Buffer.data = temp2BufferBytes + temp2Buffer.rowBytes = context.bytesPerRow + + + + vImageScale_ARGB8888(&sourceBuffer, &tempBuffer, nil, vImage_Flags(kvImageDoNotTile)) + //vImageUnpremultiplyData_ARGB8888(&tempBuffer, &tempBuffer, vImage_Flags(kvImageDoNotTile)) + + vImagePremultipliedAlphaBlend_ARGB8888(&tempBuffer, &temp2Buffer, &destinationBuffer, vImage_Flags(kvImageDoNotTile)) + //vImageCopyBuffer(&tempBuffer, &destinationBuffer, 4, vImage_Flags(kvImageDoNotTile))*/ + + 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)) + } + + self.blurredRepresentationValue = context.generateImage() + return self.blurredRepresentationValue + default: + return nil + } + } + } + static let queue = Queue(name: "ItemAnimationContext", qos: .default) private let cache: AnimationCache @@ -135,11 +276,10 @@ private final class ItemAnimationContext { private var disposable: Disposable? private var displayLink: ConstantDisplayLinkAnimator? - private var timestamp: Double = 0.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 { @@ -180,9 +320,13 @@ private final class ItemAnimationContext { } func updateAddedTarget(target: MultiAnimationRenderTarget) { - if let currentFrameGroup = self.currentFrameGroup { - if let cgImage = currentFrameGroup.image.cgImage { + 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 + } } } @@ -215,35 +359,57 @@ private final class ItemAnimationContext { return self.update(advanceTimestamp: advanceTimestamp) } - private func update(advanceTimestamp: Double?) -> LoadFrameGroupTask? { + private func update(advanceTimestamp: Double) -> LoadFrameGroupTask? { guard let item = self.item else { return nil } - let timestamp = self.timestamp - if let advanceTimestamp = advanceTimestamp { - self.timestamp += 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 currentFrameGroup = self.currentFrameGroup, currentFrameGroup.timestamp == self.timestamp { - } else if !self.isLoadingFrameGroup { - self.isLoadingFrameGroup = true + if let frameAdvance = frameAdvance, !self.isLoadingFrame { + self.isLoadingFrame = true return LoadFrameGroupTask(task: { [weak self] in - let currentFrameGroup = FrameGroup(item: item, timestamp: timestamp) + 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() { if let target = target.value { - target.transitionToContents(currentFrameGroup.image.cgImage!) + target.transitionToContents(currentFrame.image.cgImage!) + + if let blurredRepresentationTarget = target.blurredRepresentationTarget { + blurredRepresentationTarget.contents = currentFrame.blurredRepresentation(color: target.blurredRepresentationBackgroundColor)?.cgImage + } } } } @@ -251,7 +417,7 @@ private final class ItemAnimationContext { }) } - if let _ = self.currentFrameGroup { + if let _ = self.currentFrame { for target in self.targets.copyItems() { if let target = target.value { target.updateDisplayPlaceholder(displayPlaceholder: false) @@ -268,7 +434,13 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { 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 { @@ -284,8 +456,9 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } 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, size: size, fetch: fetch, stateUpdated: { [weak self] in @@ -294,7 +467,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } strongSelf.updateIsPlaying() }) - self.itemContexts[itemId] = itemContext + self.itemContexts[itemKey] = itemContext } let index = itemContext.targets.add(Weak(target)) @@ -302,12 +475,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) } } } @@ -320,7 +493,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 { @@ -329,18 +502,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, size: CGSize) -> Bool { if let item = cache.getFirstFrameSynchronously(sourceId: itemId, size: size) { - guard let frameGroup = FrameGroup(item: item, timestamp: 0.0) else { + 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 { @@ -357,15 +537,24 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { return } - let frameGroup = FrameGroup(item: item, timestamp: 0.0) + 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 frameGroup = frameGroup { - target.contents = frameGroup.image.cgImage + 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 { diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index 97d36a4020..736613287a 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -226,7 +226,7 @@ public final class TextNodeWithEntities { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: attemptSynchronousLoad, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: attemptSynchronousLoad, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: floor(itemSize * 1.2), height: floor(itemSize * 1.2))) self.inlineStickerItemLayers[id] = itemLayer self.textNode.layer.addSublayer(itemLayer) diff --git a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift index ddd56772f7..c59db57746 100644 --- a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift +++ b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift @@ -44,7 +44,8 @@ public func cacheVideoAnimation(path: String, width: Int, height: Int, writer: A } } } - }, proposedWidth: frame.width, proposedHeight: frame.height, duration: frameDuration) + return frameDuration + }, proposedWidth: frame.width, proposedHeight: frame.height) } else { break } 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/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 917b839354..764f39c8f9 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -8606,6 +8606,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return (ChatTextInputState(inputText: inputText, selectionRange: selectionPosition ..< selectionPosition), inputMode) } + + strongSelf.chatDisplayNode.updateTypingActivity(true) }, backwardsDeleteText: { [weak self] in guard let strongSelf = self else { return diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 016c32deda..fefc2817bb 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2836,12 +2836,21 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { if peerId?.namespace != Namespaces.Peer.SecretChat, let interactiveEmojis = self.interactiveEmojis, interactiveEmojis.emojis.contains(trimmedInputText) { messages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) } else { + var inlineStickers: [MediaId: Media] = [:] + 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 + } + } + }) + 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)) } @@ -2852,17 +2861,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { webpage = self.chatPresentationInterfaceState.urlPreview?.1 } - messages.append(.message(text: text.string, attributes: attributes, inlineStickers: [:], 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: [], inlineStickers: [:], 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)) } } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 22b3258fb6..4aa93627c8 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -79,19 +79,66 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let isPremiumDisabled = premiumConfiguration.isPremiumDisabled let emojiItems: Signal = combineLatest( - context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), - hasPremium + context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: [Namespaces.OrderedItemList.LocalRecentEmoji], namespaces: [Namespaces.ItemCollection.CloudEmojiPacks], aroundIndex: nil, count: 10000000), + hasPremium, + context.account.viewTracker.featuredEmojiPacks() ) - |> map { view, hasPremium -> EmojiPagerContentComponent in + |> map { view, hasPremium, featuredEmojiPacks -> EmojiPagerContentComponent in struct ItemGroup { var supergroupId: AnyHashable var id: AnyHashable - var isPremium: Bool + var title: String + var isPremiumLocked: Bool + var isFeatured: 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 + } + + 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 + //TODO:localize + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", isPremiumLocked: false, isFeatured: false, items: [resultItem])) + } + } + } + for (subgroupId, list) in staticEmojiMapping { let groupId: AnyHashable = "static" for emojiString in list { @@ -105,11 +152,17 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, isPremium: false, items: [resultItem])) + //TODO:localize + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Emoji", isPremiumLocked: false, isFeatured: false, items: [resultItem])) } } } + var installedCollectionIds = Set() + for (id, _, _) in view.collectionInfos { + installedCollectionIds.insert(id) + } + for entry in view.entries { guard let item = entry.item as? StickerPackItem else { continue @@ -122,20 +175,50 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let supergroupId = entry.index.collectionId let groupId: AnyHashable = supergroupId - let isPremium: Bool = item.file.isPremiumEmoji && !hasPremium - if isPremium && isPremiumDisabled { + let isPremiumLocked: Bool = item.file.isPremiumEmoji && !hasPremium + if isPremiumLocked && isPremiumDisabled { continue } - /*if isPremium { - groupId = "\(supergroupId)-p" - } else { - groupId = supergroupId - }*/ if let groupIndex = itemGroupIndexById[groupId] { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, isPremium: isPremium, items: [resultItem])) + + 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, isPremiumLocked: isPremiumLocked, isFeatured: false, items: [resultItem])) + } + } + + 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, isPremiumLocked: isPremiumLocked, isFeatured: true, items: [resultItem])) + } } } @@ -146,20 +229,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { animationRenderer: animationRenderer, inputInteraction: inputInteraction, itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in - var title: String? + var hasClear = false if group.id == AnyHashable("recent") { - //TODO:localize - title = "Recently Used" - } else { - for (id, info, _) in view.collectionInfos { - if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { - title = info.title - break - } - } + hasClear = true } - return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: title, isPremium: group.isPremium, displayPremiumBadges: false, items: group.items) + return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: group.title, isFeatured: group.isFeatured, isPremiumLocked: group.isPremiumLocked, hasClear: hasClear, displayPremiumBadges: false, items: group.items) }, itemLayoutType: .compact ) @@ -244,12 +319,53 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }, openStickerSettings: { }, - openPremiumSection: { [weak controllerInteraction] in + addGroupAction: { [weak controllerInteraction] 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.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 { + let _ = context.engine.stickers.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start() + + break + } + } + }) + }, + clearGroup: { [weak controllerInteraction] groupId in guard let controllerInteraction = controllerInteraction else { return } - let controller = PremiumIntroScreen(context: context, source: .stickers) - controllerInteraction.navigationController()?.pushViewController(controller) + 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 { @@ -311,7 +427,27 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { controller.navigationPresentation = .modal controllerInteraction.navigationController()?.pushViewController(controller) }, - openPremiumSection: { + addGroupAction: { _, _ in + }, + 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) + } }, pushController: { [weak controllerInteraction] controller in guard let controllerInteraction = controllerInteraction else { @@ -366,6 +502,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { struct ItemGroup { var supergroupId: AnyHashable var id: AnyHashable + var title: String + var isPremiumLocked: Bool + var isFeatured: Bool var displayPremiumBadges: Bool var items: [EmojiPagerContentComponent.Item] } @@ -408,7 +547,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: false, items: [resultItem])) + //TODO:localize + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Saved", isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } @@ -434,7 +574,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: false, items: [resultItem])) + //TODO:localize + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } count += 1 @@ -483,7 +624,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: false, items: [resultItem])) + //TODO:localize + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Premium", isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } @@ -502,7 +644,15 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, displayPremiumBadges: true, items: [resultItem])) + + 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, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: true, items: [resultItem])) } } @@ -513,26 +663,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { animationRenderer: animationRenderer, inputInteraction: stickerInputInteraction, itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in - var title: String? - if group.id == AnyHashable("saved") { - //TODO:localize - title = "Saved" - } else if group.id == AnyHashable("recent") { - //TODO:localize - title = "Recently Used" - } else if group.id == AnyHashable("premium") { - //TODO:localize - title = "Premium" - } else { - for (id, info, _) in view.collectionInfos { - if AnyHashable(id) == group.id, let info = info as? StickerPackCollectionInfo { - title = info.title - break - } - } + var hasClear = false + if group.id == AnyHashable("recent") { + hasClear = true } - return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: title, isPremium: false, displayPremiumBadges: group.displayPremiumBadges, items: group.items) + return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: group.title, isFeatured: group.isFeatured, isPremiumLocked: group.isPremiumLocked, hasClear: hasClear, displayPremiumBadges: group.displayPremiumBadges, items: group.items) }, itemLayoutType: .detailed ) @@ -592,6 +728,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { loadMoreToken: nil )) + let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings return combineLatest(queue: .mainQueue(), emojiItems, stickerItems, @@ -603,7 +740,37 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] = [] for reaction in reactions { if let file = animatedEmojiStickers[reaction]?.first?.file { - availableGifSearchEmojies.append(EntityKeyboardComponent.GifSearchEmoji(emoji: reaction, file: file, title: reaction)) + 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)) } } @@ -995,6 +1162,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { gifContent = nil } + if let gifContentValue = gifContent { + if gifContentValue.items.isEmpty { + gifContent = nil + } + } + let entityKeyboardSize = self.entityKeyboardView.update( transition: mappedTransition, component: AnyComponent(EntityKeyboardComponent( @@ -1340,7 +1513,9 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV }, openStickerSettings: { }, - openPremiumSection: { + addGroupAction: { _, _ in + }, + clearGroup: { _ in }, pushController: { _ in }, diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 692d82c6a2..209e9bede4 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -184,9 +184,9 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: !isEmoji ? "anim_stickertosmile" : "anim_smiletosticker", - colors: colors, mode: .animateTransitionFromPrevious ), + colors: colors, size: animationFrame.size )), environment: {}, From ee4cc8599c9a0d6491a11b657662e9997ecf492a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 19 Jul 2022 03:46:32 +0200 Subject: [PATCH 065/113] [WIP] emoji --- .../StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift | 1 - .../EntityKeyboard/Sources/EmojiPagerContentComponent.swift | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift index 19d4e7d17c..0b12336a11 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -260,7 +260,6 @@ final class StickerPackEmojisItemNode: GridItemNode { renderer: animationRenderer, placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), - displayPremiumBadgeIfAvailable: false, pointSize: itemNativeFitSize, onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, _ in guard let strongSelf = self else { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index c0bb343e06..76871100e4 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -763,7 +763,7 @@ public final class EmojiPagerContentComponent: Component { 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 = 2.0 + let preScaleFactor: CGFloat = 1.0 let scaledSize = CGSize(width: floor(size.width * preScaleFactor), height: floor(size.height * preScaleFactor)) let scaleFactor = scaledSize.width / size.width @@ -1911,7 +1911,7 @@ public final class EmojiPagerContentComponent: Component { renderer: component.animationRenderer, placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), - pointSize: itemNativeFitSize, + pointSize: itemVisibleFitSize, onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { return From 97de8706435be1709dbe9d8561cd4ede2395f9f7 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Tue, 19 Jul 2022 13:18:22 +0200 Subject: [PATCH 066/113] Emoji improvements --- .../Sources/ChatController.swift | 4 +- .../Sources/EmojiPagerContentComponent.swift | 15 ++-- .../Sources/EntityKeyboard.swift | 8 ++ .../TelegramUI/Sources/ChatController.swift | 27 +++++++ .../Sources/ChatControllerNode.swift | 73 ++++++++++++++++--- .../Sources/ChatEntityKeyboardInputNode.swift | 9 +++ .../Sources/ChatInterfaceInputContexts.swift | 49 ++++++++++++- .../Sources/ChatTextInputPanelNode.swift | 31 +++++--- 8 files changed, 186 insertions(+), 30 deletions(-) diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index e0856e484f..ac9c4521d2 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 diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 76871100e4..ee2b55af85 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -769,7 +769,7 @@ public final class EmojiPagerContentComponent: Component { context.scaleBy(x: 1.0 / scaleFactor, y: 1.0 / scaleFactor) - let string = NSAttributedString(string: staticEmoji, font: Font.regular(floor(30.0 * scaleFactor)), textColor: .black) + 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: (scaledSize.width - boundingRect.width) / 2.0 + boundingRect.minX, y: (scaledSize.height - boundingRect.height) / 2.0 + boundingRect.minY)) @@ -969,6 +969,9 @@ public final class EmojiPagerContentComponent: Component { 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 @@ -1059,11 +1062,11 @@ public final class EmojiPagerContentComponent: Component { loop: for attribute in file.attributes { switch attribute { - case let .CustomEmoji(_, _, packReference): + 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.inputInteraction.navigationController(), sendSticker: { file, sourceView, sourceRect in - //return component.inputInteraction.sendSticker(file, false, false, nil, false, sourceNode, sourceRect, nil) - return false + component.inputInteraction.sendSticker?(file, false, false, nil, false, sourceView, sourceRect, nil) + return true }) component.inputInteraction.navigationController()?.view.window?.endEditing(true) @@ -1550,7 +1553,9 @@ public final class EmojiPagerContentComponent: Component { } if let (item, itemKey) = self.item(atPoint: recognizer.location(in: self)), let itemLayer = self.visibleItemLayers[itemKey] { - component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + if !itemLayer.displayPlaceholder { + component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + } } } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index b86a6fdaad..6be760700b 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -176,6 +176,14 @@ public final class EntityKeyboardComponent: Component { 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.pagerView = ComponentHostView() diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 9656d8f44d..66e2d188bc 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -294,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() @@ -10079,6 +10081,29 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G 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 @@ -13008,6 +13033,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 diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index fefc2817bb..230b858fc1 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -19,6 +19,7 @@ import GridMessageSelectionNode import SparseItemGrid import ChatPresentationInterfaceState import ChatInputPanelContainer +import PremiumUI final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem { let itemNode: OverlayMediaItemNode @@ -602,6 +603,25 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 { @@ -2820,6 +2840,47 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 } + //TODO:localize + self.controllerInteraction.displayUndo(.sticker(context: context, file: firstLockedPremiumEmoji, title: nil, text: "Subscribe to Telegram Premium to unlock premium emoji.", undoText: "More", customAction: { [weak self] in + guard let strongSelf = self else { + return + } + + var replaceImpl: ((ViewController) -> Void)? + let controller = PremiumDemoScreen(context: strongSelf.context, subject: .premiumStickers, action: { + let controller = PremiumIntroScreen(context: strongSelf.context, source: .stickers) + 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 @@ -2828,23 +2889,11 @@ 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: [], inlineStickers: [:], mediaReference: AnyMediaReference.standalone(media: TelegramMediaDice(emoji: trimmedInputText)), replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageId, localGroupingKey: nil, correlationId: nil)) } else { - var inlineStickers: [MediaId: Media] = [:] - 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 - } - } - }) - let inputText = convertMarkdownToAttributes(effectiveInputText) for text in breakChatInputText(trimChatInputText(inputText)) { diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 4aa93627c8..f5dbe9d918 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -815,6 +815,15 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } + 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: GifPagerContentComponent? { didSet { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index 7c88fd6fb8..584cbc54fa 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 diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 5298fa2532..28614e66cb 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -143,15 +143,15 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { 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 .keyboard, .stickers, .inputButtons, .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) } } @@ -413,6 +413,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { var paste: (ChatTextInputPanelPasteData) -> Void = { _ in } var updateHeight: (Bool) -> Void = { _ in } var toggleExpandMediaInput: (() -> Void)? + var switchToTextInputIfNeeded: (() -> Void)? var updateActivity: () -> Void = { } @@ -891,7 +892,7 @@ 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() } } textInputNode.view.addGestureRecognizer(recognizer) @@ -2904,6 +2905,16 @@ 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 From b56132cbc1318a4dd15e5d11407b90c59f581be8 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 20 Jul 2022 01:32:47 +0200 Subject: [PATCH 067/113] Emoji improvements --- .../Sources/BlurredBackgroundComponent.swift | 39 ++- .../Display/Source/CAAnimationUtils.swift | 4 +- .../ContainedViewLayoutTransition.swift | 4 +- submodules/Display/Source/NavigationBar.swift | 18 +- .../Sources/SoftwareGradientBackground.swift | 112 ++++++- .../Sources/EmojiPagerContentComponent.swift | 64 ++-- .../Sources/EntityKeyboard.swift | 1 + .../EntityKeyboardTopPanelComponent.swift | 73 ++++- .../Sources/TextNodeWithEntities.swift | 6 +- .../Sources/ChatEntityKeyboardInputNode.swift | 37 ++- .../Sources/ChatHistoryEntriesForView.swift | 4 +- .../ChatMessageAnimatedStickerItemNode.swift | 43 ++- .../Sources/ChatTextInputPanelNode.swift | 3 +- .../Sources/WallpaperBackgroundNode.swift | 307 ++++++++++++++---- 14 files changed, 567 insertions(+), 148 deletions(-) diff --git a/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift b/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift index 0717467711..9147ef599b 100644 --- a/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift +++ b/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift @@ -6,23 +6,56 @@ import ComponentDisplayAdapters public final class BlurredBackgroundComponent: Component { public let color: UIColor + public let tintContainerView: UIView? public init( - color: UIColor + 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 tintMaskView: UIView? + public func update(component: BlurredBackgroundComponent, availableSize: CGSize, transition: Transition) -> CGSize { - self.updateColor(color: component.color, transition: transition.containedViewLayoutTransition) + if let tintContainerView = component.tintContainerView { + self.updateColor(color: .clear, forceKeepBlur: true, transition: transition.containedViewLayoutTransition) + + let tintMaskView: UIView + if let current = self.tintMaskView { + tintMaskView = current + } else { + tintMaskView = UIView() + self.tintMaskView = tintMaskView + self.addSubview(tintMaskView) + } + + tintMaskView.backgroundColor = component.color + transition.setFrame(view: tintMaskView, frame: CGRect(origin: CGPoint(), size: availableSize)) + + if tintMaskView.mask !== tintContainerView { + tintMaskView.mask = tintContainerView + } + } else { + self.updateColor(color: component.color, transition: transition.containedViewLayoutTransition) + + if let tintMaskView = self.tintMaskView { + self.tintMaskView = nil + tintMaskView.removeFromSuperview() + } + } self.update(size: availableSize, transition: transition.containedViewLayoutTransition) return availableSize @@ -30,7 +63,7 @@ public final class BlurredBackgroundComponent: Component { } public func makeView() -> View { - return View(color: .clear, enableBlur: true) + return View(color: nil, enableBlur: true) } public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { 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 32da03d32b..5090de7910 100644 --- a/submodules/Display/Source/ContainedViewLayoutTransition.swift +++ b/submodules/Display/Source/ContainedViewLayoutTransition.swift @@ -633,7 +633,7 @@ public extension ContainedViewLayoutTransition { } 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 @@ -662,7 +662,7 @@ public extension ContainedViewLayoutTransition { } 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 diff --git a/submodules/Display/Source/NavigationBar.swift b/submodules/Display/Source/NavigationBar.swift index 19073d6ae9..701b07c14c 100644 --- a/submodules/Display/Source/NavigationBar.swift +++ b/submodules/Display/Source/NavigationBar.swift @@ -287,7 +287,7 @@ public final class NavigationBackgroundNode: ASDisplayNode { } open class BlurredBackgroundView: UIView { - private var _color: UIColor + private var _color: UIColor? private var enableBlur: Bool @@ -304,8 +304,8 @@ open class BlurredBackgroundView: UIView { } } - public init(color: UIColor, enableBlur: Bool = true) { - self._color = .clear + public init(color: UIColor?, enableBlur: Bool = true) { + self._color = nil self.enableBlur = enableBlur self.backgroundView = UIView() @@ -314,7 +314,9 @@ open class BlurredBackgroundView: UIView { self.addSubview(self.backgroundView) - self.updateColor(color: color, transition: .immediate) + if let color = color { + self.updateColor(color: color, transition: .immediate) + } } required public init?(coder: NSCoder) { @@ -322,7 +324,7 @@ open class BlurredBackgroundView: UIView { } private func updateBackgroundBlur(forceKeepBlur: Bool) { - if self.enableBlur && !sharedIsReduceTransparencyEnabled && ((self._color.alpha > .ulpOfOne && self._color.alpha < 0.95) || forceKeepBlur) { + 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)) @@ -369,16 +371,16 @@ open class BlurredBackgroundView: UIView { public func updateColor(color: UIColor, enableBlur: Bool? = nil, forceKeepBlur: Bool = false, transition: ContainedViewLayoutTransition) { let effectiveEnableBlur = enableBlur ?? self.enableBlur - if self._color.isEqual(color) && self.enableBlur == effectiveEnableBlur { + if self._color == color && self.enableBlur == effectiveEnableBlur { return } self._color = color self.enableBlur = effectiveEnableBlur if sharedIsReduceTransparencyEnabled { - transition.updateBackgroundColor(layer: self.backgroundView.layer, color: self._color.withAlphaComponent(1.0)) + transition.updateBackgroundColor(layer: self.backgroundView.layer, color: color.withAlphaComponent(1.0)) } else { - transition.updateBackgroundColor(layer: self.backgroundView.layer, color: self._color) + transition.updateBackgroundColor(layer: self.backgroundView.layer, color: color) } self.updateBackgroundBlur(forceKeepBlur: forceKeepBlur) 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/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index ee2b55af85..e5f99b7cbe 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -1522,49 +1522,53 @@ public final class EmojiPagerContentComponent: Component { if let clearIconLayer = groupHeader.clearIconLayer, clearIconLayer.frame.insetBy(dx: -4.0, dy: -4.0).contains(groupHeaderPoint) { component.inputInteraction.clearGroup(id) } - - /*for group in component.itemGroups { - if group.groupId == id { - if group.isPremium && !self.expandedPremiumGroups.contains(id) { - if self.expandedPremiumGroups.contains(id) { - self.expandedPremiumGroups.remove(id) - } else { - self.expandedPremiumGroups.insert(id) - } - - let previousItemLayout = self.itemLayout - - let transition = Transition(animation: .curve(duration: 0.25, curve: .easeInOut)) - self.state?.updated(transition: transition) - - if let previousItemLayout = previousItemLayout, let itemLayout = self.itemLayout { - let boundsOffset = itemLayout.contentSize.height - previousItemLayout.contentSize.height - self.scrollView.setContentOffset(CGPoint(x: 0.0, y: self.scrollView.contentOffset.y + boundsOffset), animated: false) - transition.animateBoundsOrigin(view: self.scrollView, from: CGPoint(x: 0.0, y: -boundsOffset), to: CGPoint(), additive: true) - } - - return - } else { - break outer - } - } - }*/ } } + var foundExactItem = false if let (item, itemKey) = self.item(atPoint: recognizer.location(in: self)), let itemLayer = self.visibleItemLayers[itemKey] { + foundExactItem = true if !itemLayer.displayPlaceholder { component.inputInteraction.performItemAction(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] { + if !itemLayer.displayPlaceholder { + component.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + } + } + } } } - private func item(atPoint point: CGPoint) -> (Item, ItemLayer.Key)? { + 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 itemLayer.frame.contains(localPoint) { + 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 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) } } @@ -1724,7 +1728,7 @@ public final class EmojiPagerContentComponent: Component { let groupBorderRadius: CGFloat = 16.0 - if itemGroup.isPremiumLocked { + if itemGroup.isPremiumLocked && !itemGroup.isFeatured { validGroupBorderIds.insert(itemGroup.groupId) let groupBorderLayer: GroupBorderLayer var groupBorderTransition = transition diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 6be760700b..8113feb2ff 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -298,6 +298,7 @@ public final class EntityKeyboardComponent: Component { if let stickerContent = component.stickerContent { var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] + for itemGroup in stickerContent.itemGroups { if let id = itemGroup.supergroupId.base as? String { let iconMapping: [String: String] = [ diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index ab8c7057d8..c0bea11664 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -1063,6 +1063,10 @@ final class EntityKeyboardTopPanelComponent: Component { 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] = [] @@ -1164,7 +1168,11 @@ final class EntityKeyboardTopPanelComponent: Component { guard let strongSelf = self else { return } + let wasReordering = strongSelf.isReordering strongSelf.updateIsReordering(isActive) + if !isActive, wasReordering { + strongSelf.endReordering() + } } ) self.reorderGestureRecognizer = reorderGestureRecognizer @@ -1327,6 +1335,18 @@ final class EntityKeyboardTopPanelComponent: Component { 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() { @@ -1348,6 +1368,11 @@ final class EntityKeyboardTopPanelComponent: Component { reorderingItemContainerView.removeFromSuperview() } + if let currentReorderingScrollDisplayLink = self.currentReorderingScrollDisplayLink { + self.currentReorderingScrollDisplayLink = nil + currentReorderingScrollDisplayLink.invalidate() + } + self.currentReorderingItemId = nil self.temporaryReorderingOrderIndex = nil @@ -1361,15 +1386,23 @@ final class EntityKeyboardTopPanelComponent: Component { } 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(reorderingItemContainerView.frame) { + 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 @@ -1377,6 +1410,34 @@ final class EntityKeyboardTopPanelComponent: Component { } } + 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 @@ -1707,6 +1768,16 @@ final class EntityKeyboardTopPanelComponent: Component { 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) + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -2.0, dy: 0.0), animated: true) + break + } + } + } /*var found = false for i in 0 ..< self.items.count { diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index 3a4ae224d0..092277a4e0 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -236,7 +236,8 @@ public final class TextNodeWithEntities { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: attemptSynchronousLoad, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: floor(itemSize * 1.2), height: floor(itemSize * 1.2))) + 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) @@ -399,7 +400,8 @@ public class ImmediateTextNodeWithEntities: TextNode { if let current = self.inlineStickerItemLayers[id] { itemLayer = current } else { - itemLayer = InlineStickerItemLayer(context: context, attemptSynchronousLoad: false, emoji: stickerItem.emoji, file: stickerItem.file, cache: cache, renderer: renderer, placeholderColor: placeholderColor, pointSize: CGSize(width: itemSize, height: itemSize)) + 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) diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index f5dbe9d918..6135f1aab9 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -496,9 +496,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let stickerItems: Signal = combineLatest( context.account.postbox.itemCollectionsView(orderedItemListCollectionIds: stickerOrderedItemListCollectionIds, namespaces: stickerNamespaces, aroundIndex: nil, count: 10000000), - hasPremium + hasPremium, + context.account.viewTracker.featuredStickerPacks() ) - |> map { view, hasPremium -> EmojiPagerContentComponent in + |> map { view, hasPremium, featuredStickerPacks -> EmojiPagerContentComponent in struct ItemGroup { var supergroupId: AnyHashable var id: AnyHashable @@ -630,6 +631,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } + var installedCollectionIds = Set() + for (id, _, _) in view.collectionInfos { + installedCollectionIds.insert(id) + } + for entry in view.entries { guard let item = entry.item as? StickerPackItem else { continue @@ -656,6 +662,33 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } + 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 + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: featuredStickerPack.info.title, isPremiumLocked: isPremiumLocked, isFeatured: true, displayPremiumBadges: false, items: [resultItem])) + } + } + } + return EmojiPagerContentComponent( id: "stickers", context: context, diff --git a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift index 4443671406..6a74a938f4 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryEntriesForView.swift @@ -135,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 _ = message.associatedMedia[MediaId(namespace: Namespaces.Media.CloudFile, id: fileId)] { + 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 diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index eceef71900..513996dde0 100644 --- a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift @@ -518,9 +518,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 +555,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 +591,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) + } } } @@ -1805,7 +1818,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 { diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 28614e66cb..f021309a7f 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -809,7 +809,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { return UIView() } - 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: 24.0, height: 24.0)) + 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)) } } } diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index 10149a2ec8..d854ea3a58 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -64,6 +64,208 @@ 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 + switch self.softlightMode { + case .whileAnimating: + useSoftlight = self.isAnimating + case .always: + useSoftlight = true + case .never: + useSoftlight = false + } + if self.isUsingSoftlight != useSoftlight { + self.isUsingSoftlight = useSoftlight + + if self.isUsingSoftlight { + 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() { + if self.suspendCompositionUpdates { + self.needsCompositionUpdate = true + return + } + + switch self.softlightMode { + case .always: + return + default: + break + } + + 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 +550,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 +668,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 +678,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 +716,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 +729,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 +815,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 = UIColor.black.cgColor } } 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 +949,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 +961,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 +970,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 +1004,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 +1027,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) { From eff0b54c198075dcabc762684ece9badd273f9a5 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Wed, 20 Jul 2022 02:24:35 +0200 Subject: [PATCH 068/113] Fix emoji hit testing --- .../EntityKeyboard/Sources/EmojiPagerContentComponent.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index e5f99b7cbe..7fe1ebdf8f 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -1553,6 +1553,10 @@ public final class EmojiPagerContentComponent: Component { 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, 2.0) { + continue + } + if let closestItemValue = closestItem { if closestItemValue.distance > distance2 { closestItem = (key, distance2) From a3db20c9728a7ae2354e271503d1d418d5683dd1 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 20 Jul 2022 08:17:54 +0200 Subject: [PATCH 069/113] Various fixes --- submodules/AppLock/Sources/AppLock.swift | 6 ++- .../Sources/ContextActionsContainerNode.swift | 13 +++--- .../ContextUI/Sources/ContextController.swift | 1 + .../ContextControllerActionsStackNode.swift | 6 ++- .../Navigation/NavigationController.swift | 43 +----------------- submodules/Display/Source/WindowContent.swift | 36 +++++++++++++-- .../LegacyComponents/Sources/PGVideoMovie.m | 4 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 2 +- .../PrivacyAndSecurityController.swift | 3 ++ .../Sources/StickerPackScreen.swift | 2 +- .../AppBadge.imageset/AppBadge@3x.png | Bin 4347 -> 3929 bytes .../Sources/ChatEntityKeyboardInputNode.swift | 6 +-- .../Sources/PeerInfo/PeerInfoScreen.swift | 13 +++--- .../Sources/TelegramRootController.swift | 7 +-- 14 files changed, 70 insertions(+), 72 deletions(-) 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/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index 0045400c43..e366f414f5 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -357,7 +357,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { private let targetSelectionIndex: Int? private var action: (() -> Void)? - var requestDismiss: () -> Void = {} + var requestDismiss: (@escaping () -> Void) -> Void = { _ in } init(presentationData: PresentationData, tip: ContextController.Tip) { self.presentationData = presentationData @@ -369,8 +369,8 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { self.buttonNode = HighlightTrackingButtonNode() self.textNode = TextNodeWithEntities() + self.textNode.textNode.displaysAsynchronously = false self.textNode.textNode.isUserInteractionEnabled = false - self.textNode.textNode.displaysAsynchronously = true var isUserInteractionEnabled = false var icon: UIImage? @@ -467,8 +467,9 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { } @objc func pressed() { - self.requestDismiss() - self.action?() + self.requestDismiss({ + self.action?() + }) } func updateLayout(widthClass: ContainerViewLayoutSizeClass, width: CGFloat, transition: ContainedViewLayoutTransition) -> CGSize { @@ -652,8 +653,8 @@ 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.requestDismiss = { - getController()?.dismiss(completion: nil) + textSelectionTipNode.requestDismiss = { completion in + getController()?.dismiss(completion: completion) } self.textSelectionTipNode = textSelectionTipNode } else { diff --git a/submodules/ContextUI/Sources/ContextController.swift b/submodules/ContextUI/Sources/ContextController.swift index 398eea1cfb..5e655079d0 100644 --- a/submodules/ContextUI/Sources/ContextController.swift +++ b/submodules/ContextUI/Sources/ContextController.swift @@ -2396,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 4b7e5ac84a..e4e72f488a 100644 --- a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift @@ -887,8 +887,8 @@ final class ContextControllerActionsStackNode: ASDisplayNode { if self.tipNode == nil { updatedTransition = .immediate let tipNode = InnerTextSelectionTipContainerNode(presentationData: presentationData, tip: tip) - tipNode.requestDismiss = { [weak self] in - self?.getController()?.dismiss(completion: nil) + tipNode.requestDismiss = { [weak self] completion in + self?.getController()?.dismiss(completion: completion) } self.tipNode = tipNode } @@ -997,6 +997,7 @@ final class ContextControllerActionsStackNode: ASDisplayNode { if animated { self.dismissingItemContainers.append((itemContainer, false)) } else { + itemContainer.tipNode?.removeFromSupernode() itemContainer.removeFromSupernode() } } @@ -1198,6 +1199,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/Display/Source/Navigation/NavigationController.swift b/submodules/Display/Source/Navigation/NavigationController.swift index 3cbd98634f..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 { @@ -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/WindowContent.swift b/submodules/Display/Source/WindowContent.swift index 82b0b44a1c..e66677cd42 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,9 @@ public class Window1 { public init(hostView: WindowHostView, statusBarHost: StatusBarHost?) { self.hostView = hostView + self.badgeView = UIImageView() + self.badgeView.image = UIImage(bundleImageName: "Components/AppBadge") + self.systemUserInterfaceStyle = hostView.systemUserInterfaceStyle let boundsSize = self.hostView.eventView.bounds.size @@ -626,8 +630,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 +655,26 @@ public class Window1 { } } + private var forceBadgeHidden = false + 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 +853,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 +893,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 +1112,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/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/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 19d1249bcd..2dc3ae0916 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -1223,7 +1223,7 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { public weak var containerView: UIView? public var animationColor: UIColor? - public init(context: AccountContext, peerId: PeerId) { + public init(context: AccountContext, peerId: PeerId, options: [CachedPremiumGiftOption]) { self.context = context var updateInProgressImpl: ((Bool) -> Void)? diff --git a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index 09f3a97eec..a20f4fe1d8 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -769,6 +769,9 @@ public func privacyAndSecurityController(context: AccountContext, initialSetting }), 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) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 576b23290f..1401791f68 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -715,7 +715,7 @@ private final class StickerPackContainer: ASDisplayNode { } else if loadedCount == contents.count { self.onReady() - if !contents.isEmpty && self.currentStickerPack == nil { + 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) } diff --git a/submodules/TelegramUI/Images.xcassets/Components/AppBadge.imageset/AppBadge@3x.png b/submodules/TelegramUI/Images.xcassets/Components/AppBadge.imageset/AppBadge@3x.png index d647852ab026fccfeff1c00eaa369fab476b824b..f9746877fdf944b445ea7c7e1030cf2fa7fdb9e8 100644 GIT binary patch delta 3910 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 U@95xI82|tP07*qoM6N<$g8V_GS^xk5 delta 4331 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 Z{}1=5P8Ra%AW;AS002ovPDHLkV1n*qfe-)y diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 22b3258fb6..0e96c35d3c 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -203,7 +203,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { if file.isPremiumEmoji && !hasPremium { //TODO:localize - + let presentationData = context.sharedContext.currentPresentationData.with { $0 } controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { [weak controllerInteraction] in guard let controllerInteraction = controllerInteraction else { @@ -211,7 +211,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } var replaceImpl: ((ViewController) -> Void)? - let controller = PremiumDemoScreen(context: context, subject: .premiumStickers, action: { + let controller = PremiumDemoScreen(context: context, subject: .animatedEmoji, action: { let controller = PremiumIntroScreen(context: context, source: .stickers) replaceImpl?(controller) }) @@ -1310,7 +1310,7 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV } var replaceImpl: ((ViewController) -> Void)? - let controller = PremiumDemoScreen(context: strongSelf.context, subject: .premiumStickers, action: { + let controller = PremiumDemoScreen(context: strongSelf.context, subject: .animatedEmoji, action: { let controller = PremiumIntroScreen(context: strongSelf.context, source: .stickers) replaceImpl?(controller) }) diff --git a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 641416b426..1f46cd824e 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -4064,7 +4064,11 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Gift"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in f(.dismissWithoutContent) - self?.giftPremium() + + if let strongSelf = self { + let controller = PremiumGiftScreen(context: strongSelf.context, peerId: strongSelf.peerId, options: cachedData.premiumGiftOptions) + strongSelf.controller?.push(controller) + } }))) } @@ -6426,12 +6430,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, UIScrollViewDelegate } })) } - - private func giftPremium() { - let controller = PremiumGiftScreen(context: self.context, peerId: self.peerId) - self.controller?.push(controller) - } - + fileprivate func switchToAccount(id: AccountRecordId) { self.accountsAndPeers.set(.never()) self.context.sharedContext.switchToAccount(id: id, fromSettingsController: nil, withChatListController: nil) diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index 73927f1538..6957009e80 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -76,11 +76,8 @@ 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) + |> deliverOn(Queue.mainQueue())).start(next: { value in + context.sharedContext.mainWindow?.setForceBadgeHidden(!value) }) } From e1902192d442529a0aa0ab6dc835bc2b1aa94e40 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 20 Jul 2022 11:46:57 +0200 Subject: [PATCH 070/113] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 2 + .../Sources/ContextActionsContainerNode.swift | 2 +- .../PremiumUI/Sources/PremiumDemoScreen.swift | 5 ++- .../Sources/StickerPackEmojisItem.swift | 38 +++++++++++++++---- .../Sources/TextNodeWithEntities.swift | 2 +- .../TelegramUI/Sources/ChatController.swift | 2 + .../Sources/ChatControllerInteraction.swift | 3 ++ .../Sources/ChatControllerNode.swift | 5 +++ .../ChatRecentActionsControllerNode.swift | 1 + .../Sources/DrawingStickersScreen.swift | 1 + .../OverlayAudioPlayerControllerNode.swift | 1 + .../Sources/PeerInfo/PeerInfoScreen.swift | 1 + .../Sources/SharedAccountContext.swift | 1 + 13 files changed, 54 insertions(+), 10 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e427b5cb88..c58baf8b04 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7890,3 +7890,5 @@ Sorry for the inconvenience."; "Conversation.VoiceMessagesRestricted" = "%@ doesn't accept voice and video messages"; "Emoji.ClearRecent" = "Clear Recent Emoji"; + +"Premium.AnimatedEmoji.Proceed" = "Unlock Animated Emoji"; diff --git a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index e366f414f5..c7507f66c9 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -400,7 +400,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { self.arguments = arguments self.file = file self.targetSelectionIndex = nil - icon = nil //UIImage(bundleImageName: "Chat/Context Menu/Arrow") + icon = nil isUserInteractionEnabled = text != nil } diff --git a/submodules/PremiumUI/Sources/PremiumDemoScreen.swift b/submodules/PremiumUI/Sources/PremiumDemoScreen.swift index 2c80a1cb54..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 } @@ -994,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 } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift index 0b12336a11..2b5a4c4404 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -172,13 +172,19 @@ final class StickerPackEmojisItemNode: GridItemNode { super.didLoad() let shimmerHostView = PortalSourceView() + shimmerHostView.alpha = 0.0 + shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.frame.size) + self.view.addSubview(shimmerHostView) self.shimmerHostView = shimmerHostView let standaloneShimmerEffect = StandaloneShimmerEffect() self.standaloneShimmerEffect = standaloneShimmerEffect - - shimmerHostView.alpha = 0.0 - self.view.addSubview(shimmerHostView) + 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 @@ -261,7 +267,7 @@ final class StickerPackEmojisItemNode: GridItemNode { placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), pointSize: itemNativeFitSize, - onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, _ in + onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { return } @@ -275,7 +281,7 @@ final class StickerPackEmojisItemNode: GridItemNode { context: context, file: item.file, shimmerView: strongSelf.shimmerHostView, - color: nil, + color: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.08), size: itemNativeFitSize ) strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView @@ -289,9 +295,20 @@ final class StickerPackEmojisItemNode: GridItemNode { } else { if let placeholderView = strongSelf.visibleItemPlaceholderViews[itemId] { strongSelf.visibleItemPlaceholderViews.removeValue(forKey: itemId) - placeholderView.removeFromSuperview() - strongSelf.updateShimmerIfNeeded() + 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() + } } } } @@ -324,6 +341,13 @@ final class StickerPackEmojisItemNode: GridItemNode { itemLayer.isVisibleForAnimations = true } + + for id in self.visibleItemLayers.keys { + if !validIds.contains(id) { + self.visibleItemLayers[id]?.removeFromSuperlayer() + self.visibleItemLayers[id] = nil + } + } } private func updateShimmerIfNeeded() { diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index 092277a4e0..9f3b56b741 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -78,7 +78,7 @@ public final class TextNodeWithEntities { context: self.context, cache: self.cache, renderer: self.renderer, - placeholderColor: self.placeholderColor, + placeholderColor: color, attemptSynchronous: self.attemptSynchronous ) } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 66e2d188bc..ab34e8964d 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -3702,6 +3702,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 diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index 36261570fc..95c6a9da12 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -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]] = [:] @@ -243,6 +244,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 +332,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 230b858fc1..b1ad2afa2d 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2317,6 +2317,10 @@ 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() @@ -2866,6 +2870,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { guard let strongSelf = self else { return } + strongSelf.dismissTextInput() var replaceImpl: ((ViewController) -> Void)? let controller = PremiumDemoScreen(context: strongSelf.context, subject: .premiumStickers, action: { diff --git a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift index 17e7d41d94..5fa9774f2f 100644 --- a/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatRecentActionsControllerNode.swift @@ -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 diff --git a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift index 0e8743ef92..97ea2d7c5e 100644 --- a/submodules/TelegramUI/Sources/DrawingStickersScreen.swift +++ b/submodules/TelegramUI/Sources/DrawingStickersScreen.swift @@ -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)) diff --git a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift index 7918d25600..928371d929 100644 --- a/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift +++ b/submodules/TelegramUI/Sources/OverlayAudioPlayerControllerNode.swift @@ -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/PeerInfo/PeerInfoScreen.swift b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift index 1f46cd824e..0653983289 100644 --- a/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Sources/PeerInfo/PeerInfoScreen.swift @@ -2356,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 diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index 260943c25f..00ae018e33 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -1334,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)) From 1a102a6d1c9564de64f412dcfe294e87400fdfea Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Wed, 20 Jul 2022 20:47:21 +0200 Subject: [PATCH 071/113] Fix undo action --- submodules/UndoUI/Sources/UndoOverlayControllerNode.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift index e962e26fb7..9915f8fae4 100644 --- a/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift +++ b/submodules/UndoUI/Sources/UndoOverlayControllerNode.swift @@ -974,6 +974,8 @@ final class UndoOverlayControllerNode: ViewControllerTracingNode { case let .sticker(_, _, _, _, _, customAction): if let customAction = customAction { customAction() + } else { + let _ = self.action(.undo) } default: let _ = self.action(.undo) From 237f86f7ca9e6eca184f73abc9ab3b648fd3583e Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Thu, 21 Jul 2022 02:11:02 +0200 Subject: [PATCH 072/113] Various fixes --- submodules/PremiumUI/Sources/PremiumIntroScreen.swift | 3 +++ submodules/TelegramUI/Sources/ChatControllerNode.swift | 4 ++-- .../TelegramUI/Sources/ChatEntityKeyboardInputNode.swift | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift index 823359e6bd..b0305e0722 100644 --- a/submodules/PremiumUI/Sources/PremiumIntroScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumIntroScreen.swift @@ -36,6 +36,7 @@ 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) @@ -73,6 +74,8 @@ 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: diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index b1ad2afa2d..6d26a9f3ce 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2873,8 +2873,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { strongSelf.dismissTextInput() var replaceImpl: ((ViewController) -> Void)? - let controller = PremiumDemoScreen(context: strongSelf.context, subject: .premiumStickers, action: { - let controller = PremiumIntroScreen(context: strongSelf.context, source: .stickers) + let controller = PremiumDemoScreen(context: strongSelf.context, subject: .animatedEmoji, action: { + let controller = PremiumIntroScreen(context: strongSelf.context, source: .animatedEmoji) replaceImpl?(controller) }) replaceImpl = { [weak controller] c in diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 65f67c2364..987a4dd009 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -287,7 +287,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var replaceImpl: ((ViewController) -> Void)? let controller = PremiumDemoScreen(context: context, subject: .animatedEmoji, action: { - let controller = PremiumIntroScreen(context: context, source: .stickers) + let controller = PremiumIntroScreen(context: context, source: .animatedEmoji) replaceImpl?(controller) }) replaceImpl = { [weak controller] c in @@ -1526,7 +1526,7 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV var replaceImpl: ((ViewController) -> Void)? let controller = PremiumDemoScreen(context: strongSelf.context, subject: .animatedEmoji, action: { - let controller = PremiumIntroScreen(context: strongSelf.context, source: .stickers) + let controller = PremiumIntroScreen(context: strongSelf.context, source: .animatedEmoji) replaceImpl?(controller) }) replaceImpl = { [weak controller] c in From fdea4fc9675a9d815939acec53477bdd453f9f14 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Thu, 21 Jul 2022 03:30:06 +0200 Subject: [PATCH 073/113] Experiment: don't drop requests --- submodules/MtProtoKit/Sources/MTRequestMessageService.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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) { From 806536a4cdf7fdcbc2040c0bf0d2fe2b11763286 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Thu, 21 Jul 2022 03:30:22 +0200 Subject: [PATCH 074/113] Emoji input improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 1 + .../PublicHeaders/ImageDCT/ImageDCT.h | 11 +- .../AnimationCache/ImageDCT/Sources/DCT.cpp | 58 +- .../AnimationCache/ImageDCT/Sources/DCT.h | 10 +- .../ImageDCT/Sources/ImageDCT.mm | 39 +- .../Sources/AnimationCache.swift | 78 +- .../AnimationCache/Sources/ImageData.swift | 47 +- .../Sources/ChatInputPanelContainer.swift | 14 +- .../Sources/EmojiPagerContentComponent.swift | 1132 +++++++++++++++-- .../Sources/EntityKeyboard.swift | 30 +- .../EntityKeyboardTopPanelComponent.swift | 2 + .../Sources/GifPagerContentComponent.swift | 1 + .../Sources/MultiAnimationRenderer.swift | 65 - .../Sources/ChatEntityKeyboardInputNode.swift | 436 +++++-- 14 files changed, 1604 insertions(+), 320 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index e427b5cb88..6e32852eaf 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -107,6 +107,7 @@ "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"; diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h index 4f9a855d4f..236cdd2f9f 100644 --- a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/PublicHeaders/ImageDCT/ImageDCT.h @@ -5,9 +5,18 @@ #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)initWithQuality:(NSInteger)quality; +- (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)); diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp index 49e464e764..fe67756534 100644 --- a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.cpp @@ -118,6 +118,16 @@ static DCTELEM std_luminance_quant_tbl[DCTSIZE2] = { 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 @@ -143,7 +153,7 @@ int jpeg_quality_scaling(int quality) return quality; } -void jpeg_add_quant_table(DCTELEM *qtable, DCTELEM *basicTable, int scale_factor, bool forceBaseline) +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 @@ -164,7 +174,7 @@ void jpeg_add_quant_table(DCTELEM *qtable, DCTELEM *basicTable, int scale_factor } } -void jpeg_set_quality(DCTELEM *qtable, int quality) +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 @@ -175,10 +185,10 @@ void jpeg_set_quality(DCTELEM *qtable, int quality) quality = jpeg_quality_scaling(quality); /* Set up standard quality tables */ - jpeg_add_quant_table(qtable, std_luminance_quant_tbl, quality, false); + jpeg_add_quant_table(qtable, basicTable, quality, false); } -void getDivisors(DCTELEM *dtbl, DCTELEM *qtable) { +void getDivisors(DCTELEM *dtbl, DCTELEM const *qtable) { #define CONST_BITS 14 #define RIGHT_SHIFT(x, shft) ((x) >> (shft)) @@ -234,22 +244,15 @@ void quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace) } } -void generateForwardDctData(int quality, std::vector &data) { +void generateForwardDctData(DCTELEM const *qtable, std::vector &data) { data.resize(DCTSIZE2 * 4 * sizeof(DCTELEM)); - - DCTELEM qtable[DCTSIZE2]; - jpeg_set_quality(qtable, quality); - getDivisors((DCTELEM *)data.data(), qtable); } -void generateInverseDctData(int quality, std::vector &data) { +void generateInverseDctData(DCTELEM const *qtable, std::vector &data) { data.resize(DCTSIZE2 * sizeof(IFAST_MULT_TYPE)); IFAST_MULT_TYPE *ifmtbl = (IFAST_MULT_TYPE *)data.data(); - DCTELEM qtable[DCTSIZE2]; - jpeg_set_quality(qtable, quality); - #define CONST_BITS 14 static const int16_t aanscales[DCTSIZE2] = { /* precomputed values scaled up by 14 bits */ @@ -338,13 +341,32 @@ void performInverseDct(int16_t const * coefficients, uint8_t *pixels, int width, 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(int quality) { + DCTInternal(DCTTable const &dctTable) { auxiliaryData = createDctAuxiliaryData(); - generateForwardDctData(quality, forwardDctData); - generateInverseDctData(quality, inverseDctData); + generateForwardDctData(dctTable.table.data(), forwardDctData); + generateInverseDctData(dctTable.table.data(), inverseDctData); } ~DCTInternal() { @@ -357,8 +379,8 @@ public: std::vector inverseDctData; }; -DCT::DCT(int quality) { - _internal = new DCTInternal(quality); +DCT::DCT(DCTTable const &dctTable) { + _internal = new DCTInternal(dctTable); } DCT::~DCT() { diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h index 3b0ca4e772..67031caa80 100644 --- a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/DCT.h @@ -3,15 +3,23 @@ #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(int quality); + DCT(DCTTable const &dctTable); ~DCT(); void forward(uint8_t const *pixels, int16_t *coefficients, int width, int height, int bytesPerRow); diff --git a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm index 3d39105531..8a50b55c4b 100644 --- a/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm +++ b/submodules/TelegramUI/Components/AnimationCache/ImageDCT/Sources/ImageDCT.mm @@ -4,6 +4,41 @@ #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; } @@ -12,10 +47,10 @@ @implementation ImageDCT -- (instancetype _Nonnull)initWithQuality:(NSInteger)quality { +- (instancetype _Nonnull)initWithTable:(ImageDCTTable * _Nonnull)table { self = [super init]; if (self != nil) { - _dct = std::unique_ptr(new dct::DCT((int)quality)); + _dct = std::unique_ptr(new dct::DCT(table->_table)); } return self; } diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 5e6e58c568..8093e31732 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -294,10 +294,10 @@ private final class AnimationCacheItemWriterInternal { } let dctData: DctData - if let current = self.currentDctData, current.quality == self.dctQuality { + if let current = self.currentDctData { dctData = current } else { - dctData = DctData(quality: self.dctQuality) + dctData = DctData(generatingTablesAtQuality: self.dctQuality) self.currentDctData = dctData } @@ -310,11 +310,18 @@ private final class AnimationCacheItemWriterInternal { yuvaSurface.dct(dctData: dctData, target: dctCoefficients) if isFirstFrame { - self.file.write(3 as UInt32) + self.file.write(4 as UInt32) self.file.write(UInt32(dctCoefficients.yPlane.width)) self.file.write(UInt32(dctCoefficients.yPlane.height)) - self.file.write(UInt32(dctData.quality)) + + 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) @@ -501,10 +508,10 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { } let dctData: DctData - if let current = self.currentDctData, current.quality == self.dctQuality { + if let current = self.currentDctData { dctData = current } else { - dctData = DctData(quality: self.dctQuality) + dctData = DctData(generatingTablesAtQuality: self.dctQuality) self.currentDctData = dctData } @@ -526,11 +533,18 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { yuvaSurface.dct(dctData: dctData, target: dctCoefficients) if isFirstFrame { - file.write(3 as UInt32) + file.write(4 as UInt32) file.write(UInt32(dctCoefficients.yPlane.width)) file.write(UInt32(dctCoefficients.yPlane.height)) - file.write(UInt32(dctData.quality)) + + 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) @@ -652,10 +666,10 @@ private final class AnimationCacheItemAccessor { private var currentFrame: CurrentFrame? private var currentYUVASurface: ImageYUVA420? - private var currentDctData: DctData + private let currentDctData: DctData private var sharedDctCoefficients: DctCoefficientsYUVA420? - init(data: Data, range: Range, frameMapping: [FrameInfo], width: Int, height: Int, dctQuality: Int) { + init(data: Data, range: Range, frameMapping: [FrameInfo], width: Int, height: Int, dctData: DctData) { self.data = data self.range = range self.width = width @@ -673,7 +687,7 @@ private final class AnimationCacheItemAccessor { self.frameMapping = resultFrameMapping self.durationMapping = durationMapping - self.currentDctData = DctData(quality: dctQuality) + self.currentDctData = dctData } private func loadNextFrame() { @@ -835,6 +849,16 @@ private final class AnimationCacheItemAccessor { } } +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 @@ -1071,7 +1095,7 @@ private func loadItem(path: String) throws -> AnimationCacheItem { } let formatVersion = readUInt32(data: compressedData, offset: offset) offset += 4 - if formatVersion != 3 { + if formatVersion != 4 { throw LoadItemError.dataError } @@ -1090,9 +1114,27 @@ private func loadItem(path: String) throws -> AnimationCacheItem { if offset + 4 > dataLength { throw LoadItemError.dataError } - let dctQuality = readUInt32(data: compressedData, offset: offset) + 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 } @@ -1119,7 +1161,11 @@ private func loadItem(path: String) throws -> AnimationCacheItem { frameMapping.append(AnimationCacheItemAccessor.FrameInfo(duration: Double(frameDuration))) } - let itemAccessor = AnimationCacheItemAccessor(data: compressedData, range: compressedFrameDataRange, frameMapping: frameMapping, width: Int(width), height: Int(height), dctQuality: Int(dctQuality)) + 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) @@ -1397,7 +1443,9 @@ public final class AnimationCacheImpl: AnimationCache { let itemFirstFramePath = "\(itemDirectoryPath)/\(sourceIdPath.fileName)-f" if FileManager.default.fileExists(atPath: itemFirstFramePath) { - return try? loadItem(path: 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)) { diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift index 6a31392a13..1c833fc60e 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -152,12 +152,33 @@ extension ImageYUVA420 { } final class DctData { - let quality: Int - let dct: ImageDCT + let lumaTable: ImageDCTTable + let lumaDct: ImageDCT - init(quality: Int) { - self.quality = quality - self.dct = ImageDCT(quality: quality) + 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(generatingTablesAtQuality quality: Int) { + self.lumaTable = ImageDCTTable(quality: quality, isChroma: false) + self.lumaDct = ImageDCT(table: self.lumaTable) + + self.chromaTable = ImageDCTTable(quality: quality, isChroma: true) + self.chromaDct = ImageDCT(table: self.chromaTable) } } @@ -168,19 +189,24 @@ extension ImageYUVA420 { 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() } @@ -191,7 +217,8 @@ extension ImageYUVA420 { targetPlane.data.withUnsafeMutableBytes { bytes in let coefficients = bytes.baseAddress!.assumingMemoryBound(to: Int16.self) - dctData.dct.forward(withPixels: sourcePixels, coefficients: coefficients, width: sourcePlane.width, height: sourcePlane.height, bytesPerRow: sourcePlane.bytesPerRow) + let dct = isChroma ? dctData.chromaDct : dctData.lumaDct + dct.forward(withPixels: sourcePixels, coefficients: coefficients, width: sourcePlane.width, height: sourcePlane.height, bytesPerRow: sourcePlane.bytesPerRow) } } } @@ -211,19 +238,24 @@ extension DctCoefficientsYUVA420 { 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() } @@ -234,7 +266,8 @@ extension DctCoefficientsYUVA420 { targetPlane.data.withUnsafeMutableBytes { bytes in let pixels = bytes.baseAddress!.assumingMemoryBound(to: UInt8.self) - dctData.dct.inverse(withCoefficients: coefficients, pixels: pixels, width: sourcePlane.width, height: sourcePlane.height, coefficientsPerRow: targetPlane.width, bytesPerRow: targetPlane.bytesPerRow) + 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) } } } diff --git a/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift index 609dee148f..a333939a18 100644 --- a/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift +++ b/submodules/TelegramUI/Components/ChatInputPanelContainer/Sources/ChatInputPanelContainer.swift @@ -24,6 +24,16 @@ private func traceScrollView(view: UIView, point: CGPoint) -> (UIScrollView?, Bo 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 @@ -87,8 +97,8 @@ private final class ExpansionPanRecognizer: UIGestureRecognizer, UIGestureRecogn 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 { - if scrollView is ListViewScroller || scrollView is GridNodeScrollerView { + 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 diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 7fe1ebdf8f..fb1133e422 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -93,41 +93,173 @@ private final class PremiumBadgeView: UIView { } } -private final class GroupHeaderLayer: SimpleLayer { +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 { + private let actionPressed: () -> Void + private let performItemAction: (EmojiPagerContentComponent.Item, UIView, CGRect, CALayer) -> Void + + private let textLayer: SimpleLayer + private var subtitleLayer: SimpleLayer? private var lockIconLayer: SimpleLayer? private(set) var clearIconLayer: SimpleLayer? + private var separatorLayer: 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)? - override init() { + init(actionPressed: @escaping () -> Void, performItemAction: @escaping (EmojiPagerContentComponent.Item, UIView, CGRect, CALayer) -> Void) { + self.actionPressed = actionPressed + self.performItemAction = performItemAction + self.textLayer = SimpleLayer() - super.init() + super.init(frame: CGRect()) - self.addSublayer(self.textLayer) - } - - override init(layer: Any) { - self.textLayer = SimpleLayer() - - super.init(layer: layer) + self.layer.addSublayer(self.textLayer) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - func update(theme: PresentationTheme, title: String, isPremiumLocked: Bool, hasClear: Bool, constrainedWidth: CGFloat) -> CGSize { + 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 + ) -> CGSize { var themeUpdated = false if self.theme !== theme { self.theme = theme themeUpdated = true } - let color = theme.chat.inputMediaPanel.stickersSectionTextColor + let textOffsetY: CGFloat + if hasTopSeparator { + textOffsetY = 9.0 + } else { + textOffsetY = 0.0 + } + + let color: UIColor + if subtitle != nil { + color = theme.chat.inputPanel.primaryTextColor + } else { + color = theme.chat.inputMediaPanel.stickersSectionTextColor + } + let subtitleColor = theme.chat.inputMediaPanel.stickersSectionTextColor let titleHorizontalOffset: CGFloat if isPremiumLocked { @@ -137,7 +269,7 @@ private final class GroupHeaderLayer: SimpleLayer { } else { lockIconLayer = SimpleLayer() self.lockIconLayer = lockIconLayer - self.addSublayer(lockIconLayer) + self.layer.addSublayer(lockIconLayer) } if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme) { let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0)) @@ -156,13 +288,44 @@ private final class GroupHeaderLayer: SimpleLayer { titleHorizontalOffset = 0.0 } - let textConstrainedWidth = constrainedWidth - titleHorizontalOffset - 10.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 string = NSAttributedString(string: title.uppercased(), font: Font.medium(12.0), textColor: color) + let font: UIFont + let stringValue: String + if subtitle == nil { + font = Font.medium(12.0) + stringValue = title.uppercased() + } else { + font = Font.semibold(16.0) + stringValue = title + } + let string = NSAttributedString(string: stringValue, 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 @@ -176,7 +339,51 @@ private final class GroupHeaderLayer: SimpleLayer { self.currentTextLayout = (title, color, textConstrainedWidth, textSize) } - self.textLayer.frame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: 0.0), size: textSize) + let textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize) + self.textLayer.frame = textFrame + + let subtitleSize: CGSize + if let subtitle = subtitle { + var updateSubtitleContents: 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 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() + }) + 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 subtitleFrame = CGRect(origin: CGPoint(x: 0.0, y: textFrame.maxY + 1.0), size: subtitleSize) + subtitleLayer.frame = subtitleFrame + } else { + subtitleSize = CGSize() + if let subtitleLayer = self.subtitleLayer { + self.subtitleLayer = nil + subtitleLayer.removeFromSuperlayer() + } + } var clearWidth: CGFloat = 0.0 if hasClear { @@ -188,7 +395,7 @@ private final class GroupHeaderLayer: SimpleLayer { updateImage = true clearIconLayer = SimpleLayer() self.clearIconLayer = clearIconLayer - self.addSublayer(clearIconLayer) + self.layer.addSublayer(clearIconLayer) } var clearSize = clearIconLayer.bounds.size if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme) { @@ -198,19 +405,393 @@ private final class GroupHeaderLayer: SimpleLayer { clearIconLayer.contents = image.cgImage } - clearIconLayer.frame = CGRect(origin: CGPoint(x: titleHorizontalOffset + textSize.width + 4.0, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize) + switch layoutType { + case .compact: + clearIconLayer.frame = CGRect(origin: CGPoint(x: titleHorizontalOffset + textSize.width + 4.0, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize) + case .detailed: + clearIconLayer.frame = CGRect(origin: CGPoint(x: constrainedSize.width - clearSize.width, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize) + } clearWidth = 4.0 + clearSize.width } - return CGSize(width: titleHorizontalOffset + textSize.width + clearWidth, height: textSize.height) + var size: CGSize + switch layoutType { + case .compact: + size = CGSize(width: titleHorizontalOffset + textSize.width + clearWidth, height: constrainedSize.height) + case .detailed: + 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.stickersSectionTextColor.withAlphaComponent(0.3).cgColor + separatorLayer.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() + } + } + + //self.backgroundColor = UIColor.lightGray.cgColor + + return size + } + + 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 = false + 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 { + 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.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1).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) + } + + let size = CGSize(width: textSize.width + 10.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 } } public final class EmojiPagerContentComponent: Component { public typealias EnvironmentType = (EntityKeyboardChildEnvironment, PagerComponentChildEnvironment) + public final class ContentAnimation { + public enum AnimationType { + case generic + case groupExpanded(id: AnyHashable) + } + + public let type: AnimationType + + public init(type: AnimationType) { + self.type = type + } + } + public final class InputInteraction { - public let performItemAction: (Item, UIView, CGRect, CALayer) -> Void + public let performItemAction: (AnyHashable, Item, UIView, CGRect, CALayer) -> Void public let deleteBackwards: () -> Void public let openStickerSettings: () -> Void public let addGroupAction: (AnyHashable, Bool) -> Void @@ -223,7 +804,7 @@ public final class EmojiPagerContentComponent: Component { public let chatPeerId: PeerId? public init( - performItemAction: @escaping (Item, UIView, CGRect, CALayer) -> Void, + performItemAction: @escaping (AnyHashable, Item, UIView, CGRect, CALayer) -> Void, deleteBackwards: @escaping () -> Void, openStickerSettings: @escaping () -> Void, addGroupAction: @escaping (AnyHashable, Bool) -> Void, @@ -297,9 +878,13 @@ public final class EmojiPagerContentComponent: Component { 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] @@ -307,18 +892,26 @@ public final class EmojiPagerContentComponent: Component { 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 } @@ -336,15 +929,27 @@ public final class EmojiPagerContentComponent: Component { 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 } @@ -387,6 +992,9 @@ public final class EmojiPagerContentComponent: Component { } public static func ==(lhs: EmojiPagerContentComponent, rhs: EmojiPagerContentComponent) -> Bool { + if lhs === rhs { + return true + } if lhs.id != rhs.id { return false } @@ -428,56 +1036,75 @@ public final class EmojiPagerContentComponent: Component { 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 containerInsets: UIEdgeInsets + var headerInsets: UIEdgeInsets + var itemInsets: UIEdgeInsets var itemGroupLayouts: [ItemGroupLayout] + var itemDefaultHeaderHeight: CGFloat + var itemFeaturedHeaderHeight: CGFloat var nativeItemSize: CGFloat let visibleItemSize: CGFloat var horizontalSpacing: CGFloat var verticalSpacing: CGFloat - var verticalGroupSpacing: CGFloat + var verticalGroupDefaultSpacing: CGFloat + var verticalGroupFeaturedSpacing: CGFloat var itemsPerRow: Int var contentSize: CGSize var premiumButtonInset: CGFloat var premiumButtonHeight: CGFloat - init(width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], itemLayoutType: ItemLayoutType) { + init(layoutType: ItemLayoutType, width: CGFloat, containerInsets: UIEdgeInsets, itemGroups: [ItemGroupDescription], expandedGroupIds: Set) { + self.layoutType = layoutType self.width = width - self.containerInsets = containerInsets self.premiumButtonInset = 6.0 self.premiumButtonHeight = 50.0 let minItemsPerRow: Int let minSpacing: CGFloat - switch itemLayoutType { + switch layoutType { case .compact: minItemsPerRow = 8 self.nativeItemSize = 36.0 self.verticalSpacing = 9.0 minSpacing = 9.0 + self.itemDefaultHeaderHeight = 24.0 + self.itemFeaturedHeaderHeight = self.itemDefaultHeaderHeight + self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 12.0, bottom: containerInsets.bottom, right: containerInsets.right + 12.0) + self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 12.0, bottom: containerInsets.bottom, right: containerInsets.right + 12.0) case .detailed: minItemsPerRow = 5 - self.nativeItemSize = 76.0 + self.nativeItemSize = 71.0 self.verticalSpacing = 2.0 - minSpacing = 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.verticalGroupSpacing = 18.0 + self.verticalGroupDefaultSpacing = 18.0 + self.verticalGroupFeaturedSpacing = 15.0 - let itemHorizontalSpace = width - self.containerInsets.left - self.containerInsets.right + let itemHorizontalSpace = width - self.itemInsets.left - self.itemInsets.right self.itemsPerRow = max(minItemsPerRow, Int((itemHorizontalSpace + minSpacing) / (self.nativeItemSize + minSpacing))) @@ -485,29 +1112,78 @@ public final class EmojiPagerContentComponent: Component { self.horizontalSpacing = floor((itemHorizontalSpace - self.visibleItemSize * CGFloat(self.itemsPerRow)) / CGFloat(self.itemsPerRow - 1)) - var verticalGroupOrigin: CGFloat = self.containerInsets.top + 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 { - itemTopOffset += 24.0 + 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 } - let numRowsInGroup = (itemGroup.itemCount + (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 { + 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: itemGroup.itemCount + itemCount: visibleItemCount, + collapsedItemIndex: collapsedItemIndex, + collapsedItemText: collapsedItemText )) - verticalGroupOrigin += groupContentSize.height + self.verticalGroupSpacing + verticalGroupOrigin += groupContentSize.height + groupSpacing } - verticalGroupOrigin += self.containerInsets.bottom + verticalGroupOrigin += self.itemInsets.bottom self.contentSize = CGSize(width: width, height: verticalGroupOrigin) } @@ -519,7 +1195,7 @@ public final class EmojiPagerContentComponent: Component { return CGRect( origin: CGPoint( - x: self.containerInsets.left + CGFloat(column) * (self.visibleItemSize + self.horizontalSpacing), + x: self.itemInsets.left + CGFloat(column) * (self.visibleItemSize + self.horizontalSpacing), y: groupLayout.frame.minY + groupLayout.itemTopOffset + CGFloat(row) * (self.visibleItemSize + self.verticalSpacing) ), size: CGSize( @@ -538,7 +1214,7 @@ public final class EmojiPagerContentComponent: Component { if !rect.intersects(group.frame) { continue } - let offsetRect = rect.offsetBy(dx: -self.containerInsets.left, dy: -group.frame.minY - group.itemTopOffset) + 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))) @@ -740,11 +1416,11 @@ public final class EmojiPagerContentComponent: Component { } }) } - } else if let dimensions = file.dimensions { + } else if let _ = file.dimensions { let isSmall: Bool = false self.disposable = (chatMessageSticker(account: context.account, file: file, small: isSmall, synchronousLoad: attemptSynchronousLoad)).start(next: { [weak self] resultTransform in let boundingSize = CGSize(width: 93.0, height: 93.0) - let imageSize = dimensions.cgSize.aspectFilled(boundingSize) + let imageSize = boundingSize//dimensions.cgSize.aspectFitted(boundingSize) if let image = resultTransform(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .fill(.clear)))?.generateImage() { Queue.mainQueue().async { @@ -911,6 +1587,8 @@ public final class EmojiPagerContentComponent: Component { 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 @@ -956,6 +1634,7 @@ public final class EmojiPagerContentComponent: Component { 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) @@ -1168,7 +1847,7 @@ public final class EmojiPagerContentComponent: Component { anchorFrame = group.frame } - var scrollPosition = anchorFrame.minY + floor(-itemLayout.verticalGroupSpacing / 2.0) - pagerEnvironment.containerInsets.top + 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 } @@ -1186,12 +1865,12 @@ public final class EmojiPagerContentComponent: Component { for (id, view) in self.visibleItemPlaceholderViews { previousVisiblePlaceholderViews[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) } - var previousVisibleGroupHeaders: [AnyHashable: (CALayer, CGRect)] = [:] - for (id, layer) in self.visibleGroupHeaders { - if !self.scrollView.bounds.intersects(layer.frame) { + var previousVisibleGroupHeaders: [AnyHashable: (UIView, CGRect)] = [:] + for (id, view) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(view.frame) { continue } - previousVisibleGroupHeaders[id] = (layer, layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) + previousVisibleGroupHeaders[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) } var previousVisibleGroupBorders: [AnyHashable: (CALayer, CGRect)] = [:] for (id, layer) in self.visibleGroupBorders { @@ -1203,11 +1882,15 @@ public final class EmojiPagerContentComponent: Component { previousVisibleGroupPremiumButtons[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) } } + var previousVisibleGroupExpandActionButtons: [AnyHashable: (UIView, 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) + self.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: true, previousItemPositions: nil, updatedItemPositions: nil) var commonItemOffset: CGFloat? var previousVisibleBoundingRect: CGRect? @@ -1244,9 +1927,9 @@ public final class EmojiPagerContentComponent: Component { } for (id, layerAndFrame) in previousVisibleGroupHeaders { - if let layer = self.visibleGroupHeaders[id] { - if commonItemOffset == nil, self.scrollView.bounds.intersects(layer.frame) { - let visibleFrame = layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + 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 @@ -1291,6 +1974,22 @@ public final class EmojiPagerContentComponent: Component { } } + 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 @@ -1323,17 +2022,17 @@ public final class EmojiPagerContentComponent: Component { }) } - for (_, layer) in self.visibleGroupHeaders { - layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + 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, layerAndFrame) in previousVisibleGroupHeaders { + for (id, viewAndFrame) in previousVisibleGroupHeaders { if self.visibleGroupHeaders[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() + 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() }) } @@ -1366,6 +2065,20 @@ public final class EmojiPagerContentComponent: Component { 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) + 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() + }) + } } else if let previousVisibleBoundingRect = previousVisibleBoundingRect { var updatedVisibleBoundingRect: CGRect? @@ -1385,11 +2098,11 @@ public final class EmojiPagerContentComponent: Component { updatedVisibleBoundingRect = frame } } - for (_, layer) in self.visibleGroupHeaders { - if !self.scrollView.bounds.intersects(layer.frame) { + for (_, view) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(view.frame) { continue } - let frame = layer.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) + let frame = view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY) if let updatedVisibleBoundingRectValue = updatedVisibleBoundingRect { updatedVisibleBoundingRect = frame.union(updatedVisibleBoundingRectValue) } else { @@ -1410,6 +2123,18 @@ public final class EmojiPagerContentComponent: Component { } } } + 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 @@ -1452,21 +2177,21 @@ public final class EmojiPagerContentComponent: Component { }) } - for (_, layer) in self.visibleGroupHeaders { - if !self.scrollView.bounds.intersects(layer.frame) { + for (_, view) in self.visibleGroupHeaders { + if !self.scrollView.bounds.intersects(view.frame) { continue } - layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) + view.layer.animatePosition(from: CGPoint(x: 0.0, y: commonItemOffset), to: CGPoint(), duration: duration, timingFunction: timingFunction, additive: true) } - for (id, layerAndFrame) in previousVisibleGroupHeaders { + for (id, viewAndFrame) in previousVisibleGroupHeaders { if self.visibleGroupHeaders[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() + 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() }) } @@ -1504,6 +2229,21 @@ public final class EmojiPagerContentComponent: Component { 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) + 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() + }) + } } } } @@ -1518,28 +2258,37 @@ public final class EmojiPagerContentComponent: Component { 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.layer.convert(locationInScrollView, to: groupHeader) + 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.inputInteraction.clearGroup(id) + } 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.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + component.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.inputInteraction.performItemAction(item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + component.inputInteraction.performItemAction(itemKey.groupId, item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) } } } + + let _ = foundItem } } @@ -1604,7 +2353,7 @@ public final class EmojiPagerContentComponent: Component { return } - self.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false) + self.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false, previousItemPositions: nil, updatedItemPositions: nil) self.updateScrollingOffset(isReset: false, transition: .immediate) } @@ -1678,7 +2427,7 @@ public final class EmojiPagerContentComponent: Component { self.updateScrollingOffset(isReset: false, transition: transition) } - private func updateVisibleItems(transition: Transition, attemptSynchronousLoads: Bool) { + 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 theme = self.theme, let itemLayout = self.itemLayout else { return } @@ -1690,10 +2439,13 @@ public final class EmojiPagerContentComponent: Component { 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) + for groupItems in itemLayout.visibleItems(for: effectiveVisibleBounds) { let itemGroup = component.itemGroups[groupItems.groupIndex] let itemGroupLayout = itemLayout.itemGroupLayouts[groupItems.groupIndex] @@ -1708,31 +2460,72 @@ public final class EmojiPagerContentComponent: Component { var headerSizeUpdated = false if let title = itemGroup.title { validGroupHeaderIds.insert(itemGroup.groupId) - let groupHeaderLayer: GroupHeaderLayer + let groupHeaderView: GroupHeaderLayer var groupHeaderTransition = transition if let current = self.visibleGroupHeaders[itemGroup.groupId] { - groupHeaderLayer = current + groupHeaderView = current } else { groupHeaderTransition = .immediate - groupHeaderLayer = GroupHeaderLayer() - self.visibleGroupHeaders[itemGroup.groupId] = groupHeaderLayer - self.scrollView.layer.addSublayer(groupHeaderLayer) + let groupId = itemGroup.groupId + groupHeaderView = GroupHeaderLayer( + actionPressed: { [weak self] in + guard let strongSelf = self, let component = strongSelf.component else { + return + } + component.inputInteraction.addGroupAction(groupId, false) + }, + performItemAction: { [weak self] item, view, rect, layer in + guard let strongSelf = self, let component = strongSelf.component else { + return + } + component.inputInteraction.performItemAction(groupId, item, view, rect, layer) + } + ) + self.visibleGroupHeaders[itemGroup.groupId] = groupHeaderView + self.scrollView.addSubview(groupHeaderView) } - let groupHeaderSize = groupHeaderLayer.update(theme: theme, title: title, isPremiumLocked: itemGroup.isPremiumLocked, hasClear: itemGroup.hasClear, constrainedWidth: itemLayout.contentSize.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right) - if groupHeaderLayer.bounds.size != groupHeaderSize { + var actionButtonTitle: String? + if case .detailed = itemLayout.layoutType, itemGroup.isFeatured { + actionButtonTitle = itemGroup.actionButtonTitle + } + + var hasTopSeparator = false + if case .detailed = itemLayout.layoutType, itemGroup.isFeatured, groupItems.groupIndex != 0 { + hasTopSeparator = true + } + + let groupHeaderSize = groupHeaderView.update( + context: component.context, + theme: 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 } let groupHeaderFrame = CGRect(origin: CGPoint(x: floor((itemLayout.contentSize.width - groupHeaderSize.width) / 2.0), y: itemGroupLayout.frame.minY + 1.0), size: groupHeaderSize) - groupHeaderLayer.bounds = CGRect(origin: CGPoint(), size: groupHeaderFrame.size) - groupHeaderTransition.setPosition(layer: groupHeaderLayer, position: CGPoint(x: groupHeaderFrame.midX, y: groupHeaderFrame.midY)) + groupHeaderView.bounds = CGRect(origin: CGPoint(), size: groupHeaderFrame.size) + groupHeaderTransition.setPosition(view: groupHeaderView, position: CGPoint(x: groupHeaderFrame.midX, y: groupHeaderFrame.midY)) headerSize = CGSize(width: groupHeaderSize.width, height: groupHeaderSize.height) } let groupBorderRadius: CGFloat = 16.0 - if itemGroup.isPremiumLocked && !itemGroup.isFeatured { + if itemGroup.isPremiumLocked && !itemGroup.isFeatured && !itemGroup.isEmbedded { validGroupBorderIds.insert(itemGroup.groupId) let groupBorderLayer: GroupBorderLayer var groupBorderTransition = transition @@ -1750,7 +2543,7 @@ public final class EmojiPagerContentComponent: Component { groupBorderLayer.fillColor = nil } - let groupBorderHorizontalInset: CGFloat = itemLayout.containerInsets.left - 4.0 + let groupBorderHorizontalInset: CGFloat = itemLayout.itemInsets.left - 4.0 let groupBorderVerticalTopOffset: CGFloat = 8.0 let groupBorderVerticalInset: CGFloat = 6.0 @@ -1792,8 +2585,8 @@ public final class EmojiPagerContentComponent: Component { groupBorderTransition.setFrame(layer: groupBorderLayer, frame: groupBorderFrame) } - if itemGroup.isPremiumLocked || itemGroup.isFeatured { - let groupPremiumButtonMeasuringFrame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.maxY - 50.0 + 1.0), size: CGSize(width: 100.0, height: 50.0)) + 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) @@ -1864,13 +2657,12 @@ public final class EmojiPagerContentComponent: Component { } )), environment: {}, - containerSize: CGSize(width: itemLayout.width - itemLayout.containerInsets.left - itemLayout.containerInsets.right, height: itemLayout.premiumButtonHeight) + containerSize: CGSize(width: itemLayout.width - itemLayout.itemInsets.left - itemLayout.itemInsets.right, height: itemLayout.premiumButtonHeight) ) - let groupPremiumButtonFrame = CGRect(origin: CGPoint(x: itemLayout.containerInsets.left, y: itemGroupLayout.frame.maxY - groupPremiumButtonSize.height + 1.0), size: groupPremiumButtonSize) + 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 { - view.layer.anchorPoint = CGPoint(x: 0.5, y: 0.0) animateIn = true self.scrollView.addSubview(view) } @@ -1883,7 +2675,33 @@ public final class EmojiPagerContentComponent: Component { } } - if let groupItemRange = groupItems.groupItems { + 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) + } + + let baseItemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: collapsedItemIndex) + let buttonSize = groupExpandActionButton.update(theme: 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] @@ -1905,6 +2723,7 @@ public final class EmojiPagerContentComponent: Component { let itemNativeFitSize = itemDimensions.fitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) + var animateItemIn = false var updateItemLayerPlaceholder = false var itemTransition = transition let itemLayer: ItemLayer @@ -1913,6 +2732,7 @@ public final class EmojiPagerContentComponent: Component { } else { updateItemLayerPlaceholder = true itemTransition = .immediate + animateItemIn = !transition.animation.isImmediate itemLayer = ItemLayer( item: item, @@ -1981,11 +2801,26 @@ public final class EmojiPagerContentComponent: Component { 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.setPosition(layer: itemLayer, position: itemPosition) itemTransition.setBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) + if animateItemIn, !transition.animation.isImmediate { + if let previousItemPosition = previousItemPositions?[itemId] { + 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 @@ -2013,7 +2848,22 @@ public final class EmojiPagerContentComponent: Component { for (id, itemLayer) in self.visibleItemLayers { if !validIds.contains(id) { removedIds.append(id) - itemLayer.removeFromSuperlayer() + + if !transition.animation.isImmediate { + if let position = updatedItemPositions?[id] { + 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 { @@ -2029,7 +2879,16 @@ public final class EmojiPagerContentComponent: Component { for (id, groupHeaderLayer) in self.visibleGroupHeaders { if !validGroupHeaderIds.contains(id) { removedGroupHeaderIds.append(id) - groupHeaderLayer.removeFromSuperlayer() + + if !transition.animation.isImmediate { + groupHeaderLayer.alpha = 0.0 + groupHeaderLayer.layer.animateScale(from: 1.0, to: 0.5, duration: 0.2) + groupHeaderLayer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak groupHeaderLayer] _ in + groupHeaderLayer?.removeFromSuperview() + }) + } else { + groupHeaderLayer.removeFromSuperview() + } } } for id in removedGroupHeaderIds { @@ -2058,6 +2917,17 @@ public final class EmojiPagerContentComponent: Component { self.visibleGroupPremiumButtons.removeValue(forKey: id) } + var removedGroupExpandActionButtonIds: [AnyHashable] = [] + for (id, button) in self.visibleGroupExpandActionButtons { + if !validGroupExpandActionButtons.contains(id) { + removedGroupExpandActionButtonIds.append(id) + button.removeFromSuperview() + } + } + for id in removedGroupExpandActionButtonIds { + self.visibleGroupExpandActionButtons.removeValue(forKey: id) + } + if removedPlaceholerViews { self.updateShimmerIfNeeded() } @@ -2075,6 +2945,12 @@ public final class EmojiPagerContentComponent: Component { } } + 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)))) + } + func update(component: EmojiPagerContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { let previousComponent = self.component @@ -2097,8 +2973,35 @@ public final class EmojiPagerContentComponent: Component { let shimmerForegroundColor = keyboardChildEnvironment.theme.list.itemBlocksBackgroundColor.withMultipliedAlpha(0.15) self.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, previousComponent.itemGroups != component.itemGroups { + 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 { @@ -2128,13 +3031,21 @@ public final class EmojiPagerContentComponent: Component { hasTitle: itemGroup.title != nil, isPremiumLocked: itemGroup.isPremiumLocked, isFeatured: itemGroup.isFeatured, - itemCount: itemGroup.items.count + itemCount: itemGroup.items.count, + isEmbedded: itemGroup.isEmbedded, + isExpandable: itemGroup.isExpandable )) } var itemTransition = transition - let itemLayout = ItemLayout(width: availableSize.width, containerInsets: UIEdgeInsets(top: pagerEnvironment.containerInsets.top + 9.0, left: pagerEnvironment.containerInsets.left + 12.0, bottom: 9.0 + pagerEnvironment.containerInsets.bottom, right: pagerEnvironment.containerInsets.right + 12.0), itemGroups: itemGroups, itemLayoutType: component.itemLayoutType) + 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 @@ -2162,7 +3073,7 @@ public final class EmojiPagerContentComponent: Component { let effectiveVisibleSize = strongSelf.scrollView.bounds.size if strongSelf.effectiveVisibleSize != effectiveVisibleSize { strongSelf.effectiveVisibleSize = effectiveVisibleSize - strongSelf.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false) + strongSelf.updateVisibleItems(transition: .immediate, attemptSynchronousLoads: false, previousItemPositions: nil, updatedItemPositions: nil) } }) } @@ -2210,7 +3121,28 @@ public final class EmojiPagerContentComponent: Component { self.ignoreScrolling = false - self.updateVisibleItems(transition: itemTransition, attemptSynchronousLoads: !(scrollView.isDragging || scrollView.isDecelerating)) + 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 } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 8113feb2ff..4fc8b78481 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -78,6 +78,7 @@ public final class EntityKeyboardComponent: Component { 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? @@ -96,6 +97,7 @@ public final class EntityKeyboardComponent: Component { emojiContent: EmojiPagerContentComponent, stickerContent: EmojiPagerContentComponent?, gifContent: GifPagerContentComponent?, + hasRecentGifs: Bool, availableGifSearchEmojies: [GifSearchEmoji], defaultToEmojiTab: Bool, externalTopPanelContainer: PagerExternalTopPanelContainer?, @@ -113,6 +115,7 @@ public final class EntityKeyboardComponent: Component { self.emojiContent = emojiContent self.stickerContent = stickerContent self.gifContent = gifContent + self.hasRecentGifs = hasRecentGifs self.availableGifSearchEmojies = availableGifSearchEmojies self.defaultToEmojiTab = defaultToEmojiTab self.externalTopPanelContainer = externalTopPanelContainer @@ -142,6 +145,9 @@ public final class EntityKeyboardComponent: Component { if lhs.gifContent != rhs.gifContent { return false } + if lhs.hasRecentGifs != rhs.hasRecentGifs { + return false + } if lhs.availableGifSearchEmojies != rhs.availableGifSearchEmojies { return false } @@ -219,18 +225,20 @@ public final class EntityKeyboardComponent: Component { contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(gifContent))) var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] //TODO:localize - topGifItems.append(EntityKeyboardTopPanelComponent.Item( - id: "recent", - isReorderable: false, - content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: "Chat/Input/Media/RecentTabIcon", - theme: component.theme, - title: "Recent", - pressed: { [weak self] in - self?.component?.switchToGifSubject(.recent) - } + if component.hasRecentGifs { + topGifItems.append(EntityKeyboardTopPanelComponent.Item( + id: "recent", + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + imageName: "Chat/Input/Media/RecentTabIcon", + theme: component.theme, + title: "Recent", + pressed: { [weak self] in + self?.component?.switchToGifSubject(.recent) + } + )) )) - )) + } topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: "trending", isReorderable: false, diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index c0bea11664..1921cbb023 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -437,6 +437,7 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { self.scrollView.showsVerticalScrollIndicator = false self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.alwaysBounceHorizontal = false + self.scrollView.scrollsToTop = false self.scrollView.delegate = self self.scrollViewContainer.addSubview(self.scrollView) @@ -1114,6 +1115,7 @@ final class EntityKeyboardTopPanelComponent: Component { self.scrollView.showsVerticalScrollIndicator = false self.scrollView.showsHorizontalScrollIndicator = false self.scrollView.alwaysBounceHorizontal = true + self.scrollView.scrollsToTop = false self.scrollView.delegate = self self.addSubview(self.scrollView) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index 3ff0d8f0f8..c6676fbaf3 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -439,6 +439,7 @@ public final class GifPagerContentComponent: Component { } self.scrollView.showsVerticalScrollIndicator = true self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.scrollsToTop = false self.scrollView.delegate = self self.addSubview(self.scrollView) diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index ffe00bae70..b76800a424 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -107,27 +107,6 @@ private final class ItemAnimationContext { data.withUnsafeBytes { bytes -> Void in memcpy(context.bytes, bytes.baseAddress!, height * bytesPerRow) - - /*var sourceBuffer = vImage_Buffer() - sourceBuffer.width = UInt(width) - sourceBuffer.height = UInt(height) - sourceBuffer.data = UnsafeMutableRawPointer(mutating: bytes.baseAddress!.advanced(by: firstFrame.range.lowerBound)) - sourceBuffer.rowBytes = bytesPerRow - - var destinationBuffer = vImage_Buffer() - destinationBuffer.width = UInt(32) - destinationBuffer.height = UInt(32) - destinationBuffer.data = context.bytes - destinationBuffer.rowBytes = bytesPerRow - - vImageBoxConvolve_ARGB8888(&sourceBuffer, - &destinationBuffer, - nil, - UInt(width - 32 - 16), UInt(height - 32 - 16), - UInt32(31), - UInt32(31), - nil, - vImage_Flags(kvImageEdgeExtend))*/ } guard let image = context.generateImage() else { @@ -184,42 +163,6 @@ private final class ItemAnimationContext { destinationBuffer.data = context.bytes destinationBuffer.rowBytes = context.bytesPerRow - /*var sourceBuffer = vImage_Buffer() - sourceBuffer.width = UInt(width) - sourceBuffer.height = UInt(height) - sourceBuffer.data = UnsafeMutableRawPointer(mutating: bytes.baseAddress!) - sourceBuffer.rowBytes = bytesPerRow - - let tempBufferBytes = malloc(blurredHeight * context.bytesPerRow) - defer { - free(tempBufferBytes) - } - let temp2BufferBytes = malloc(blurredHeight * context.bytesPerRow) - defer { - free(temp2BufferBytes) - } - memset(temp2BufferBytes, Int32(bitPattern: color?.argb ?? 0xffffffff), blurredHeight * context.bytesPerRow) - - var tempBuffer = vImage_Buffer() - tempBuffer.width = UInt(blurredWidth) - tempBuffer.height = UInt(blurredHeight) - tempBuffer.data = tempBufferBytes - tempBuffer.rowBytes = context.bytesPerRow - - var temp2Buffer = vImage_Buffer() - temp2Buffer.width = UInt(blurredWidth) - temp2Buffer.height = UInt(blurredHeight) - temp2Buffer.data = temp2BufferBytes - temp2Buffer.rowBytes = context.bytesPerRow - - - - vImageScale_ARGB8888(&sourceBuffer, &tempBuffer, nil, vImage_Flags(kvImageDoNotTile)) - //vImageUnpremultiplyData_ARGB8888(&tempBuffer, &tempBuffer, vImage_Flags(kvImageDoNotTile)) - - vImagePremultipliedAlphaBlend_ARGB8888(&tempBuffer, &temp2Buffer, &destinationBuffer, vImage_Flags(kvImageDoNotTile)) - //vImageCopyBuffer(&tempBuffer, &destinationBuffer, 4, vImage_Flags(kvImageDoNotTile))*/ - vImageBoxConvolve_ARGB8888(&destinationBuffer, &destinationBuffer, nil, @@ -302,14 +245,6 @@ private final class ItemAnimationContext { } strongSelf.item = result.item strongSelf.updateIsPlaying() - - if result.item == nil { - for target in strongSelf.targets.copyItems() { - if let target = target.value { - target.updateDisplayPlaceholder(displayPlaceholder: true) - } - } - } } }) } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 6135f1aab9..ad7920f3ef 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -23,6 +23,7 @@ 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 { @@ -45,17 +46,37 @@ private let staticEmojiMapping: [(EmojiPagerContentComponent.StaticEmojiSegment, 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: GifPagerContentComponent? + var gifs: EntityKeyboardGifContent? var availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] init( emoji: EmojiPagerContentComponent, stickers: EmojiPagerContentComponent?, - gifs: GifPagerContentComponent?, + gifs: EntityKeyboardGifContent?, availableGifSearchEmojies: [EntityKeyboardComponent.GifSearchEmoji] ) { self.emoji = emoji @@ -88,8 +109,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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] = [] @@ -134,7 +157,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } else { itemGroupIndexById[groupId] = itemGroups.count //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", isPremiumLocked: false, isFeatured: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) } } } @@ -153,7 +176,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } else { itemGroupIndexById[groupId] = itemGroups.count //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Emoji", isPremiumLocked: false, isFeatured: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Emoji", subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) } } } @@ -191,7 +214,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { break inner } } - itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, isPremiumLocked: isPremiumLocked, isFeatured: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: false, isExpandable: false, items: [resultItem])) } } @@ -217,7 +240,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, isPremiumLocked: isPremiumLocked, isFeatured: true, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: supergroupId, id: groupId, title: featuredEmojiPack.info.title, subtitle: nil, isPremiumLocked: isPremiumLocked, isFeatured: true, isExpandable: true, items: [resultItem])) } } } @@ -234,7 +257,20 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { hasClear = true } - return EmojiPagerContentComponent.ItemGroup(supergroupId: group.supergroupId, groupId: group.id, title: group.title, isFeatured: group.isFeatured, isPremiumLocked: group.isPremiumLocked, hasClear: hasClear, displayPremiumBadges: false, items: group.items) + 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 ) @@ -256,7 +292,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { |> distinctUntilChanged let emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak interfaceInteraction, weak controllerInteraction] item, _, _, _ in + performItemAction: { [weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in guard let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { return @@ -397,12 +433,44 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { chatPeerId: chatPeerId ) let stickerInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak controllerInteraction, weak interfaceInteraction] item, view, rect, layer in + 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 } - if let file = item.file { + 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) @@ -427,7 +495,52 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { controller.navigationPresentation = .modal controllerInteraction.navigationController()?.pushViewController(controller) }, - addGroupAction: { _, _ in + 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.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start() + + 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 { @@ -447,6 +560,20 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }) ])]) 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 @@ -494,16 +621,22 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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.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 -> EmojiPagerContentComponent in + |> 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 @@ -528,6 +661,50 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } + 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 { @@ -549,13 +726,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } else { itemGroupIndexById[groupId] = itemGroups.count //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Saved", isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Saved", subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } if let recentStickers = recentStickers { - var count = 0 for item in recentStickers.items { guard let item = item.contents.get(RecentMediaItem.self) else { continue @@ -576,12 +752,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } else { itemGroupIndexById[groupId] = itemGroups.count //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) - } - - count += 1 - if count >= 5 { - break + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } @@ -626,16 +797,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } else { itemGroupIndexById[groupId] = itemGroups.count //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Premium", isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Premium", subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } - var installedCollectionIds = Set() - for (id, _, _) in view.collectionInfos { - installedCollectionIds.insert(id) - } - for entry in view.entries { guard let item = entry.item as? StickerPackItem else { continue @@ -658,7 +824,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { break inner } } - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: true, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: title, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: true, items: [resultItem])) } } @@ -684,7 +850,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: featuredStickerPack.info.title, isPremiumLocked: isPremiumLocked, isFeatured: true, displayPremiumBadges: false, items: [resultItem])) + + 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])) } } } @@ -697,11 +866,28 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { inputInteraction: stickerInputInteraction, 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, isFeatured: group.isFeatured, isPremiumLocked: group.isPremiumLocked, hasClear: hasClear, displayPremiumBadges: group.displayPremiumBadges, items: group.items) + 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 ) @@ -752,16 +938,18 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { ) // We are going to subscribe to the actual data when the view is loaded - let gifItems: Signal = .single(GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: .recent, - items: [], - isLoading: false, - loadMoreToken: nil + let gifItems: Signal = .single(EntityKeyboardGifContent( + hasRecentGifs: true, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: .recent, + items: [], + isLoading: false, + loadMoreToken: nil + ) )) - let strings = context.sharedContext.currentPresentationData.with({ $0 }).strings return combineLatest(queue: .mainQueue(), emojiItems, stickerItems, @@ -822,6 +1010,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private let defaultToEmojiTab: Bool private var currentInputData: InputData private var inputDataDisposable: Disposable? + private var hasRecentGifsDisposable: Disposable? private let controllerInteraction: ChatControllerInteraction? @@ -839,10 +1028,11 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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 scheduledInnerTransition: Transition? - private var gifMode: GifPagerContentComponent.Subject = .recent { + private var gifMode: GifPagerContentComponent.Subject? { didSet { - if self.gifMode != oldValue { + if let gifMode = self.gifMode, gifMode != oldValue { self.reloadGifContext() } } @@ -858,17 +1048,17 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } private final class GifContext { - private var componentValue: GifPagerContentComponent? { + private var componentValue: EntityKeyboardGifContent? { didSet { if let componentValue = self.componentValue { self.componentResult.set(.single(componentValue)) } } } - private let componentPromise = Promise() + private let componentPromise = Promise() - private let componentResult = Promise() - var component: Signal { + private let componentResult = Promise() + var component: Signal { return self.componentResult.get() } private var componentDisposable: Disposable? @@ -884,29 +1074,37 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.subject = subject self.gifInputInteraction = gifInputInteraction - let gifItems: Signal + 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 -> GifPagerContentComponent in + |> map { savedGifs -> EntityKeyboardGifContent in var items: [GifPagerContentComponent.Item] = [] for gifItem in savedGifs { items.append(GifPagerContentComponent.Item( file: gifItem.contents.get(RecentMediaItem.self)!.media )) } - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: subject, - items: items, - isLoading: false, - loadMoreToken: nil + return EntityKeyboardGifContent( + hasRecentGifs: true, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: false, + loadMoreToken: nil + ) ) } case .trending: - gifItems = trendingGifs - |> map { trendingGifs -> GifPagerContentComponent in + gifItems = combineLatest(hasRecentGifs, trendingGifs) + |> map { hasRecentGifs, trendingGifs -> EntityKeyboardGifContent in var items: [GifPagerContentComponent.Item] = [] var isLoading = false @@ -920,18 +1118,21 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { isLoading = true } - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: subject, - items: items, - isLoading: isLoading, - loadMoreToken: nil + return EntityKeyboardGifContent( + hasRecentGifs: hasRecentGifs, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: isLoading, + loadMoreToken: nil + ) ) } case let .emojiSearch(query): - gifItems = paneGifSearchForQuery(context: context, query: query, offset: nil, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil) - |> map { result -> GifPagerContentComponent in + 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? @@ -947,13 +1148,16 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { isLoading = true } - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: subject, - items: items, - isLoading: isLoading, - loadMoreToken: loadMoreToken + return EntityKeyboardGifContent( + hasRecentGifs: hasRecentGifs, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: isLoading, + loadMoreToken: loadMoreToken + ) ) } } @@ -988,12 +1192,17 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { switch self.subject { case let .emojiSearch(query): - let gifItems: Signal - gifItems = paneGifSearchForQuery(context: context, query: query, offset: token, incompleteResults: true, staleCachedResults: true, delayRequest: false, updateActivity: nil) - |> map { result -> GifPagerContentComponent in + 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.items { + for item in componentValue.component.items { items.append(item) existingIds.insert(item.file.fileId) } @@ -1015,13 +1224,16 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { isLoading = true } - return GifPagerContentComponent( - context: context, - inputInteraction: gifInputInteraction, - subject: subject, - items: items, - isLoading: isLoading, - loadMoreToken: loadMoreToken + return EntityKeyboardGifContent( + hasRecentGifs: hasRecentGifs, + component: GifPagerContentComponent( + context: context, + inputInteraction: gifInputInteraction, + subject: subject, + items: items, + isLoading: isLoading, + loadMoreToken: loadMoreToken + ) ) } @@ -1038,7 +1250,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } } - private let gifComponent = Promise() + private let gifComponent = Promise() private var gifInputInteraction: GifPagerContentComponent.InputInteraction? init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction?) { @@ -1059,6 +1271,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.externalTopPanelContainerImpl = PagerExternalTopPanelContainer() + self.inputDataDisposable = (combineLatest(queue: .mainQueue(), updatedInputData, self.gifComponent.get() @@ -1070,8 +1283,12 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var inputData = inputData inputData.gifs = gifs + var transition: Transition = .immediate + if strongSelf.currentInputData.emoji != inputData.emoji { + transition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(EmojiPagerContentComponent.ContentAnimation(type: .generic)) + } strongSelf.currentInputData = inputData - strongSelf.performLayout() + strongSelf.performLayout(transition: transition) }) self.inputNodeInteraction = ChatMediaInputNodeInteraction( @@ -1137,16 +1354,35 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - self.reloadGifContext() + 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 { - self.gifContext = GifContext(context: self.context, subject: self.gifMode, gifInputInteraction: gifInputInteraction, trendingGifs: self.trendingGifsPromise.get()) + if let gifInputInteraction = self.gifInputInteraction, let gifMode = self.gifMode { + self.gifContext = GifContext(context: self.context, subject: gifMode, gifInputInteraction: gifInputInteraction, trendingGifs: self.trendingGifsPromise.get()) } } @@ -1154,16 +1390,25 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { self.isMarkInputCollapsed = true } - private func performLayout() { + 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 @@ -1179,14 +1424,14 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { let inputNodeInteraction = self.inputNodeInteraction! let trendingGifsPromise = self.trendingGifsPromise - var mappedTransition = Transition(transition) + var mappedTransition = innerTransition if wasMarkedInputCollapsed || !isExpanded { mappedTransition = mappedTransition.withUserData(EntityKeyboardComponent.MarkInputCollapsed()) } var stickerContent: EmojiPagerContentComponent? = self.currentInputData.stickers - var gifContent: GifPagerContentComponent? = self.currentInputData.gifs + var gifContent: EntityKeyboardGifContent? = self.currentInputData.gifs var stickersEnabled = true if let peer = interfaceState.renderedPeer?.peer as? TelegramChannel { @@ -1204,12 +1449,6 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { gifContent = nil } - if let gifContentValue = gifContent { - if gifContentValue.items.isEmpty { - gifContent = nil - } - } - let entityKeyboardSize = self.entityKeyboardView.update( transition: mappedTransition, component: AnyComponent(EntityKeyboardComponent( @@ -1217,7 +1456,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { bottomInset: bottomInset, emojiContent: self.currentInputData.emoji, stickerContent: stickerContent, - gifContent: gifContent, + gifContent: gifContent?.component, + hasRecentGifs: gifContent?.hasRecentGifs ?? false, availableGifSearchEmojies: self.currentInputData.availableGifSearchEmojies, defaultToEmojiTab: self.defaultToEmojiTab, externalTopPanelContainer: self.externalTopPanelContainerImpl, @@ -1483,7 +1723,7 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV self.clipsToBounds = true let inputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak self] item, _, _, _ in + performItemAction: { [weak self] _, item, _, _, _ in guard let strongSelf = self else { return } From 3384d86415d805a8c9503217cba84370f5c4e3a4 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Thu, 21 Jul 2022 03:47:42 +0200 Subject: [PATCH 075/113] Fix animation --- .../Sources/ChatEntityKeyboardInputNode.swift | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 03f950533a..b77c7bb21e 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -1284,7 +1284,17 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { inputData.gifs = gifs var transition: Transition = .immediate - if strongSelf.currentInputData.emoji != inputData.emoji { + 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 { transition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(EmojiPagerContentComponent.ContentAnimation(type: .generic)) } strongSelf.currentInputData = inputData From 7b663a3445ad7a68e32f2742bd63f914bf506b0a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 22 Jul 2022 02:12:10 +0200 Subject: [PATCH 076/113] Emoji input improvements --- .../Sources/Node/ChatListItem.swift | 31 +- .../Sources/Node/ChatListItemStrings.swift | 11 +- .../Sources/BlurredBackgroundComponent.swift | 99 ++- .../Sources/PagerComponent.swift | 26 +- submodules/Display/Source/NavigationBar.swift | 1 + .../Sources/ItemListStickerPackItem.swift | 3 +- .../InstalledStickerPacksController.swift | 2 +- .../StickerPackInteractiveOperations.swift | 9 +- .../Stickers/TelegramEngineStickers.swift | 2 +- .../Resources/PresentationResourceKey.swift | 4 +- .../Resources/PresentationResourcesChat.swift | 12 +- .../Sources/ServiceMessageStrings.swift | 7 +- .../Sources/EmojiPagerContentComponent.swift | 715 ++++++++++++++++-- .../Sources/EntityKeyboard.swift | 20 +- .../Sources/GifPagerContentComponent.swift | 17 +- .../Sources/TextNodeWithEntities.swift | 8 +- .../GridDismissIcon.imageset/Contents.json | 20 +- .../GridDismissIcon.imageset/Frame 1.svg | 4 + .../StickersGroupCross@2x-1.png | Bin 508 -> 0 bytes .../StickersGroupCross@3x.png | Bin 576 -> 0 bytes .../TelegramUI/Sources/ChatController.swift | 40 + .../Sources/ChatControllerNode.swift | 34 +- .../Sources/ChatEntityKeyboardInputNode.swift | 674 +++++++++-------- .../ChatMediaInputStickerGridItem.swift | 2 +- .../Sources/ChatMessageActionItemNode.swift | 30 + .../Sources/ChatMessageItemView.swift | 2 +- ...StickerPanePeerSpecificSetupGridItem.swift | 2 +- .../StickerPaneTrendingListGridItem.swift | 2 +- 28 files changed, 1311 insertions(+), 466 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/Frame 1.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@2x-1.png delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/GridDismissIcon.imageset/StickersGroupCross@3x.png diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index ab5dcb5491..d61f1342de 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -556,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)" } @@ -590,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)" } @@ -1095,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]) } @@ -1104,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 @@ -1125,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) @@ -1156,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 @@ -1185,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) } @@ -1216,10 +1218,17 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { 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, message: message._asMessage()) - } else if let spoilers = spoilers { + } 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 { @@ -1268,8 +1277,6 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { attributedText = composedString - - var displayMediaPreviews = true if message._asMessage().containsSecretMedia { displayMediaPreviews = false @@ -1359,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 { 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/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift b/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift index 9147ef599b..df5f156d2a 100644 --- a/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift +++ b/submodules/Components/BlurredBackgroundComponent/Sources/BlurredBackgroundComponent.swift @@ -27,36 +27,93 @@ public final class BlurredBackgroundComponent: Component { } public final class View: BlurredBackgroundView { - private var tintMaskView: UIView? + private var tintContainerView: UIView? + private var vibrancyEffectView: UIVisualEffectView? public func update(component: BlurredBackgroundComponent, availableSize: CGSize, transition: Transition) -> CGSize { - if let tintContainerView = component.tintContainerView { - self.updateColor(color: .clear, forceKeepBlur: true, transition: transition.containedViewLayoutTransition) + /*if self.tintContainerView !== component.tintContainerView { + if let tintContainerView = self.tintContainerView { + self.tintContainerView = nil + if tintContainerView.superview === self { + tintContainerView.removeFromSuperview() + } + } - let tintMaskView: UIView - if let current = self.tintMaskView { - tintMaskView = current + 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 { - tintMaskView = UIView() - self.tintMaskView = tintMaskView - self.addSubview(tintMaskView) - } - - tintMaskView.backgroundColor = component.color - transition.setFrame(view: tintMaskView, frame: CGRect(origin: CGPoint(), size: availableSize)) - - if tintMaskView.mask !== tintContainerView { - tintMaskView.mask = tintContainerView + if let vibrancyEffectView = self.vibrancyEffectView { + self.vibrancyEffectView = nil + vibrancyEffectView.removeFromSuperview() + } } + }*/ + + self.updateColor(color: component.color, transition: transition.containedViewLayoutTransition) + + /*if let _ = self.viewWithTag(123) { } else { - self.updateColor(color: component.color, transition: transition.containedViewLayoutTransition) + let blurEffect = UIBlurEffect(style: .extraLight) - if let tintMaskView = self.tintMaskView { - self.tintMaskView = nil - tintMaskView.removeFromSuperview() - } + + /*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 } diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index d6db0ca729..a042fd5b3b 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -12,6 +12,10 @@ 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 @@ -292,8 +296,15 @@ public final class PagerComponent 0.0 { - paneTransitionGestureState.fraction = recognizer.translation(in: self).x / self.bounds.width + 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) @@ -554,6 +565,7 @@ public final class PagerComponent var contentBackgroundTransition = panelStateTransition @@ -565,13 +577,13 @@ public final class PagerComponent .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") { 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/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index 6800b1ee04..062fa9be06 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -729,7 +729,7 @@ 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 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 })) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/StickerPackInteractiveOperations.swift index 46562bcf55..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 { @@ -33,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) }) } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift index 1d9f5cce72..4159f4464a 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Stickers/TelegramEngineStickers.swift @@ -46,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) } diff --git a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift index a8174639c5..38bc5537d3 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourceKey.swift @@ -276,7 +276,6 @@ public enum PresentationResourceKey: Int32 { case chatKeyboardActionButtonProfileIcon case chatKeyboardActionButtonAddToChatIcon case chatKeyboardActionButtonWebAppIcon - case chatEntityKeyboardLock case uploadToneIcon } @@ -313,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 280bae0544..51d10d9031 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.stickersSectionTextColor) + 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) }) } @@ -1282,9 +1282,9 @@ public struct PresentationResourcesChat { }) } - public static func chatEntityKeyboardLock(_ theme: PresentationTheme) -> UIImage? { - return theme.image(PresentationResourceKey.chatEntityKeyboardLock.rawValue, { theme in - return generateTintedImage(image: UIImage(bundleImageName: "Chat/Stickers/SmallLock"), color: theme.chat.inputMediaPanel.stickersSectionTextColor) + 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/Stickers/SmallLock"), color: color) }) } } diff --git a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift index 9d3bbd9f01..22e99077a1 100644 --- a/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/ServiceMessageStrings.swift @@ -34,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 } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index fb1133e422..75ee7ec788 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -29,6 +29,328 @@ private let premiumBadgeIcon: UIImage? = generateTintedImage(image: UIImage(bund 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? @@ -191,14 +513,24 @@ private final class GroupHeaderActionButton: UIButton { } 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? @@ -208,15 +540,23 @@ private final class GroupHeaderLayer: UIView { 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) { @@ -254,12 +594,15 @@ private final class GroupHeaderLayer: UIView { } let color: UIColor + let needsTintText: Bool if subtitle != nil { color = theme.chat.inputPanel.primaryTextColor + needsTintText = false } else { - color = theme.chat.inputMediaPanel.stickersSectionTextColor + color = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1) + needsTintText = true } - let subtitleColor = theme.chat.inputMediaPanel.stickersSectionTextColor + let subtitleColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1) let titleHorizontalOffset: CGFloat if isPremiumLocked { @@ -271,7 +614,7 @@ private final class GroupHeaderLayer: UIView { self.lockIconLayer = lockIconLayer self.layer.addSublayer(lockIconLayer) } - if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme) { + if let image = PresentationResourcesChat.chatEntityKeyboardLock(theme, color: color) { let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0)) lockIconLayer.contents = image.cgImage titleHorizontalOffset = imageSize.width + 2.0 @@ -280,11 +623,31 @@ private final class GroupHeaderLayer: UIView { lockIconLayer.contents = nil titleHorizontalOffset = 0.0 } + + 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) { + let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0)) + tintLockIconLayer.contents = image.cgImage + tintLockIconLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: imageSize) + } 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() + } titleHorizontalOffset = 0.0 } @@ -319,13 +682,14 @@ private final class GroupHeaderLayer: UIView { let font: UIFont let stringValue: String if subtitle == nil { - font = Font.medium(12.0) + 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 @@ -336,19 +700,31 @@ private final class GroupHeaderLayer: UIView { 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(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize) self.textLayer.frame = textFrame + self.tintTextLayer.frame = textFrame + self.tintTextLayer.isHidden = !needsTintText 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 @@ -359,6 +735,14 @@ private final class GroupHeaderLayer: UIView { 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) } @@ -375,8 +759,22 @@ private final class GroupHeaderLayer: UIView { 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 { @@ -387,8 +785,9 @@ private final class GroupHeaderLayer: UIView { var clearWidth: CGFloat = 0.0 if hasClear { - let clearIconLayer: SimpleLayer var updateImage = themeUpdated + + let clearIconLayer: SimpleLayer if let current = self.clearIconLayer { clearIconLayer = current } else { @@ -397,13 +796,24 @@ private final class GroupHeaderLayer: UIView { 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) { + if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1)) { clearSize = image.size - clearSize.width = 10.0 - clearSize.height = 10.0 clearIconLayer.contents = image.cgImage } + if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: .white) { + tintClearIconLayer.contents = image.cgImage + } switch layoutType { case .compact: @@ -411,7 +821,17 @@ private final class GroupHeaderLayer: UIView { case .detailed: 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 @@ -464,17 +884,30 @@ private final class GroupHeaderLayer: UIView { self.separatorLayer = separatorLayer self.layer.addSublayer(separatorLayer) } - separatorLayer.backgroundColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withAlphaComponent(0.3).cgColor + separatorLayer.backgroundColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withAlphaComponent(0.15).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() + } } - //self.backgroundColor = UIColor.lightGray.cgColor - return size } @@ -557,7 +990,7 @@ private final class GroupEmbeddedView: UIScrollView, UIScrollViewDelegate, Pager self.showsVerticalScrollIndicator = true self.showsHorizontalScrollIndicator = false self.delegate = self - self.clipsToBounds = false + self.clipsToBounds = true self.scrollsToTop = false } @@ -678,22 +1111,37 @@ private final class GroupEmbeddedView: UIScrollView, UIScrollViewDelegate, Pager } 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) @@ -741,7 +1189,8 @@ private final class GroupExpandActionButton: UIButton { let textConstrainedWidth: CGFloat = 100.0 let color = theme.list.itemCheckColors.foregroundColor - self.backgroundLayer.backgroundColor = theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1).cgColor + self.backgroundLayer.backgroundColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1).cgColor + self.tintContainerLayer.backgroundColor = UIColor.white.cgColor let textSize: CGSize if let currentTextLayout = self.currentTextLayout, currentTextLayout.string == title, currentTextLayout.color == color, currentTextLayout.constrainedWidth == textConstrainedWidth { @@ -768,7 +1217,9 @@ private final class GroupExpandActionButton: UIButton { 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 } @@ -781,6 +1232,7 @@ public final class EmojiPagerContentComponent: Component { public enum AnimationType { case generic case groupExpanded(id: AnyHashable) + case groupInstalled(id: AnyHashable) } public let type: AnimationType @@ -790,6 +1242,13 @@ public final class EmojiPagerContentComponent: Component { } } + 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 @@ -969,7 +1428,7 @@ public final class EmojiPagerContentComponent: Component { public let context: AccountContext public let animationCache: AnimationCache public let animationRenderer: MultiAnimationRenderer - public let inputInteraction: InputInteraction + public let inputInteractionHolder: InputInteractionHolder public let itemGroups: [ItemGroup] public let itemLayoutType: ItemLayoutType @@ -978,7 +1437,7 @@ public final class EmojiPagerContentComponent: Component { context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, - inputInteraction: InputInteraction, + inputInteractionHolder: InputInteractionHolder, itemGroups: [ItemGroup], itemLayoutType: ItemLayoutType ) { @@ -986,7 +1445,7 @@ public final class EmojiPagerContentComponent: Component { self.context = context self.animationCache = animationCache self.animationRenderer = animationRenderer - self.inputInteraction = inputInteraction + self.inputInteractionHolder = inputInteractionHolder self.itemGroups = itemGroups self.itemLayoutType = itemLayoutType } @@ -1007,7 +1466,7 @@ public final class EmojiPagerContentComponent: Component { if lhs.animationRenderer !== rhs.animationRenderer { return false } - if lhs.inputInteraction !== rhs.inputInteraction { + if lhs.inputInteractionHolder !== rhs.inputInteractionHolder { return false } if lhs.itemGroups != rhs.itemGroups { @@ -1028,7 +1487,7 @@ public final class EmojiPagerContentComponent: Component { } } - public final class View: UIView, UIScrollViewDelegate, ComponentTaggedView { + public final class View: UIView, UIScrollViewDelegate, PagerContentViewWithBackground, ComponentTaggedView { private struct ItemGroupDescription: Equatable { let supergroupId: AnyHashable let groupId: AnyHashable @@ -1553,11 +2012,35 @@ public final class EmojiPagerContentComponent: Component { } } - private final class GroupBorderLayer: CAShapeLayer { + 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() } @@ -1569,14 +2052,80 @@ public final class EmojiPagerContentComponent: Component { 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() @@ -1604,16 +2153,23 @@ public final class EmojiPagerContentComponent: Component { private weak var peekController: PeekController? override init(frame: CGRect) { + self.backgroundView = BlurredBackgroundView(color: nil) + self.shimmerHostView = PortalSourceView() self.standaloneShimmerEffect = StandaloneShimmerEffect() - self.scrollView = ContentScrollView() + 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) + self.shimmerHostView.alpha = 0.0 self.addSubview(self.shimmerHostView) @@ -1673,7 +2229,7 @@ public final class EmojiPagerContentComponent: Component { let presentationData = context.sharedContext.currentPresentationData.with { $0 } - if let sendSticker = component.inputInteraction.sendSticker, let chatPeerId = component.inputInteraction.chatPeerId { + 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) @@ -1712,7 +2268,7 @@ public final class EmojiPagerContentComponent: Component { |> deliverOnMainQueue).start(next: { result in switch result { case .generic: - component.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 })) + 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 @@ -1721,10 +2277,10 @@ public final class EmojiPagerContentComponent: Component { } else { text = presentationData.strings.Premium_MaxFavedStickersText("\(premiumLimit)").string } - component.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 + 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.inputInteraction.pushController(controller) + component.inputInteractionHolder.inputInteraction?.pushController(controller) return true } return false @@ -1743,13 +2299,13 @@ public final class EmojiPagerContentComponent: Component { 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.inputInteraction.navigationController(), sendSticker: { file, sourceView, sourceRect in - component.inputInteraction.sendSticker?(file, false, false, nil, false, sourceView, sourceRect, nil) + 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.inputInteraction.navigationController()?.view.window?.endEditing(true) - component.inputInteraction.presentController(controller) + component.inputInteractionHolder.inputInteraction?.navigationController()?.view.window?.endEditing(true) + component.inputInteractionHolder.inputInteraction?.presentController(controller) } break loop default: @@ -1761,7 +2317,7 @@ public final class EmojiPagerContentComponent: Component { 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.inputInteraction.pushController(controller) + component.inputInteractionHolder.inputInteraction?.pushController(controller) })) } }, present: { [weak self] content, sourceView, sourceRect in @@ -1779,7 +2335,7 @@ public final class EmojiPagerContentComponent: Component { self?.simulateUpdateLayout(isVisible: !visible) }*/ strongSelf.peekController = controller - component.inputInteraction.presentGlobalOverlayController(controller) + component.inputInteractionHolder.inputInteraction?.presentGlobalOverlayController(controller) return controller }, updateContent: { [weak self] content in guard let strongSelf = self else { @@ -1865,14 +2421,14 @@ public final class EmojiPagerContentComponent: Component { for (id, view) in self.visibleItemPlaceholderViews { previousVisiblePlaceholderViews[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) } - var previousVisibleGroupHeaders: [AnyHashable: (UIView, CGRect)] = [:] + 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: (CALayer, CGRect)] = [:] + 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)) } @@ -1882,7 +2438,7 @@ public final class EmojiPagerContentComponent: Component { previousVisibleGroupPremiumButtons[id] = (view, view.frame.offsetBy(dx: 0.0, dy: -self.scrollView.bounds.minY)) } } - var previousVisibleGroupExpandActionButtons: [AnyHashable: (UIView, CGRect)] = [:] + 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)) } @@ -2031,8 +2587,11 @@ public final class EmojiPagerContentComponent: Component { } 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 + 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() }) } @@ -2045,8 +2604,11 @@ public final class EmojiPagerContentComponent: Component { } 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 + 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() }) } @@ -2075,8 +2637,11 @@ public final class EmojiPagerContentComponent: Component { } 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 + 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 { @@ -2190,8 +2755,11 @@ public final class EmojiPagerContentComponent: Component { 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 + 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() }) } @@ -2208,8 +2776,11 @@ public final class EmojiPagerContentComponent: Component { 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 + 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() }) } @@ -2240,8 +2811,11 @@ public final class EmojiPagerContentComponent: Component { 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 + 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() }) } } @@ -2260,7 +2834,7 @@ public final class EmojiPagerContentComponent: Component { 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.inputInteraction.clearGroup(id) + component.inputInteractionHolder.inputInteraction?.clearGroup(id) } else { if groupHeader.tapGesture(recognizer) { return @@ -2275,7 +2849,7 @@ public final class EmojiPagerContentComponent: Component { foundExactItem = true foundItem = true if !itemLayer.displayPlaceholder { - component.inputInteraction.performItemAction(itemKey.groupId, item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + component.inputInteractionHolder.inputInteraction?.performItemAction(itemKey.groupId, item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) } } @@ -2283,7 +2857,7 @@ public final class EmojiPagerContentComponent: Component { if let (item, itemKey) = self.item(atPoint: recognizer.location(in: self), extendedHitRange: true), let itemLayer = self.visibleItemLayers[itemKey] { foundItem = true if !itemLayer.displayPlaceholder { - component.inputInteraction.performItemAction(itemKey.groupId, item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) + component.inputInteractionHolder.inputInteraction?.performItemAction(itemKey.groupId, item, self, self.scrollView.convert(itemLayer.frame, to: self), itemLayer) } } } @@ -2445,6 +3019,10 @@ public final class EmojiPagerContentComponent: Component { let topVisibleDetectionBounds = effectiveVisibleBounds.offsetBy(dx: 0.0, dy: pagerEnvironment.containerInsets.top) let contentAnimation = transition.userData(ContentAnimation.self) + var transitionHintInstalledGroupId: AnyHashable? + if let contentAnimation = contentAnimation, case let .groupInstalled(groupId) = contentAnimation.type { + transitionHintInstalledGroupId = groupId + } for groupItems in itemLayout.visibleItems(for: effectiveVisibleBounds) { let itemGroup = component.itemGroups[groupItems.groupIndex] @@ -2472,17 +3050,18 @@ public final class EmojiPagerContentComponent: Component { guard let strongSelf = self, let component = strongSelf.component else { return } - component.inputInteraction.addGroupAction(groupId, false) + 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.inputInteraction.performItemAction(groupId, item, view, rect, layer) + 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? @@ -2536,8 +3115,10 @@ public final class EmojiPagerContentComponent: Component { groupBorderLayer = GroupBorderLayer() self.visibleGroupBorders[itemGroup.groupId] = groupBorderLayer self.scrollView.layer.insertSublayer(groupBorderLayer, at: 0) + self.mirrorContentScrollView.layer.addSublayer(groupBorderLayer.tintContainerLayer) - groupBorderLayer.strokeColor = theme.chat.inputMediaPanel.stickersSectionTextColor.cgColor + groupBorderLayer.strokeColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1).cgColor + groupBorderLayer.tintContainerLayer.strokeColor = UIColor.white.cgColor groupBorderLayer.lineWidth = 1.6 groupBorderLayer.lineCap = .round groupBorderLayer.fillColor = nil @@ -2653,7 +3234,7 @@ public final class EmojiPagerContentComponent: Component { guard let strongSelf = self, let component = strongSelf.component else { return } - component.inputInteraction.addGroupAction(groupId, isPremiumLocked) + component.inputInteractionHolder.inputInteraction?.addGroupAction(groupId, isPremiumLocked) } )), environment: {}, @@ -2693,6 +3274,7 @@ public final class EmojiPagerContentComponent: Component { }) self.visibleGroupExpandActionButtons[itemGroup.groupId] = groupExpandActionButton self.scrollView.addSubview(groupExpandActionButton) + self.mirrorContentScrollView.layer.addSublayer(groupExpandActionButton.tintContainerLayer) } let baseItemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: collapsedItemIndex) @@ -2805,7 +3387,7 @@ public final class EmojiPagerContentComponent: Component { itemTransition.setBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) if animateItemIn, !transition.animation.isImmediate { - if let previousItemPosition = previousItemPositions?[itemId] { + if let previousItemPosition = previousItemPositions?[itemId], transitionHintInstalledGroupId != itemId.groupId { itemTransition = transition itemLayer.position = previousItemPosition } else { @@ -2850,7 +3432,7 @@ public final class EmojiPagerContentComponent: Component { removedIds.append(id) if !transition.animation.isImmediate { - if let position = updatedItemPositions?[id] { + if let position = updatedItemPositions?[id], transitionHintInstalledGroupId != id.groupId { transition.setPosition(layer: itemLayer, position: position, completion: { [weak itemLayer] _ in itemLayer?.removeFromSuperlayer() }) @@ -2883,11 +3465,14 @@ public final class EmojiPagerContentComponent: Component { if !transition.animation.isImmediate { groupHeaderLayer.alpha = 0.0 groupHeaderLayer.layer.animateScale(from: 1.0, to: 0.5, duration: 0.2) - groupHeaderLayer.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, completion: { [weak groupHeaderLayer] _ in + 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() } } } @@ -2900,6 +3485,7 @@ public final class EmojiPagerContentComponent: Component { if !validGroupBorderIds.contains(id) { removedGroupBorderIds.append(id) groupBorderLayer.removeFromSuperlayer() + groupBorderLayer.tintContainerLayer.removeFromSuperlayer() } } for id in removedGroupBorderIds { @@ -2922,6 +3508,7 @@ public final class EmojiPagerContentComponent: Component { if !validGroupExpandActionButtons.contains(id) { removedGroupExpandActionButtonIds.append(id) button.removeFromSuperview() + button.tintContainerLayer.removeFromSuperlayer() } } for id in removedGroupExpandActionButtonIds { @@ -2951,6 +3538,29 @@ public final class EmojiPagerContentComponent: Component { 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 theme = self.theme else { + return + } + + if self.vibrancyEffectView == nil { + let blurEffect = UIBlurEffect(style: .extraLight) + let vibrancyEffect = UIVibrancyEffect(blurEffect: blurEffect) + let vibrancyEffectView = UIVisualEffectView(effect: vibrancyEffect) + self.vibrancyEffectView = vibrancyEffectView + self.backgroundView.addSubview(vibrancyEffectView) + vibrancyEffectView.contentView.addSubview(self.mirrorContentScrollView) + } + + self.backgroundView.updateColor(color: theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75), 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 @@ -2960,11 +3570,11 @@ public final class EmojiPagerContentComponent: Component { self.peekRecognizer?.isEnabled = component.itemLayoutType == .detailed let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value + let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value self.theme = keyboardChildEnvironment.theme self.activeItemUpdated = keyboardChildEnvironment.getContentActiveItemUpdated(component.id) - let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value self.pagerEnvironment = pagerEnvironment transition.setFrame(view: self.shimmerHostView, frame: CGRect(origin: CGPoint(), size: availableSize)) @@ -3049,6 +3659,8 @@ public final class EmojiPagerContentComponent: Component { if let previousItemLayout = self.itemLayout { if previousItemLayout.width != itemLayout.width { itemTransition = .immediate + } else if transition.userData(ContentAnimation.self) == nil { + itemTransition = .immediate } } else { itemTransition = .immediate @@ -3111,7 +3723,10 @@ public final class EmojiPagerContentComponent: Component { 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 } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 4fc8b78481..3bc5e874cd 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -171,6 +171,8 @@ public final class EntityKeyboardComponent: Component { } public final class View: UIView { + private let tintContainerView: UIView + private let pagerView: ComponentHostView private var component: EntityKeyboardComponent? @@ -191,6 +193,7 @@ public final class EntityKeyboardComponent: Component { } override init(frame: CGRect) { + self.tintContainerView = UIView() self.pagerView = ComponentHostView() super.init(frame: frame) @@ -392,7 +395,7 @@ public final class EntityKeyboardComponent: Component { maxSize: nil )), action: { - stickerContent.inputInteraction.openStickerSettings() + stickerContent.inputInteractionHolder.inputInteraction?.openStickerSettings() } ).minSize(CGSize(width: 38.0, height: 38.0))))) } @@ -494,7 +497,7 @@ public final class EntityKeyboardComponent: Component { component.switchToTextInput() } ).minSize(CGSize(width: 38.0, height: 38.0))))) - let deleteBackwards = component.emojiContent.inputInteraction.deleteBackwards + let deleteBackwards = component.emojiContent.inputInteractionHolder.inputInteraction?.deleteBackwards contentAccessoryRightButtons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(Button( content: AnyComponent(BundleIconComponent( name: "Chat/Input/Media/EntityInputClearIcon", @@ -502,11 +505,11 @@ public final class EntityKeyboardComponent: Component { maxSize: nil )), action: { - deleteBackwards() + deleteBackwards?() AudioServicesPlaySystemSound(1155) } ).withHoldAction({ - deleteBackwards() + deleteBackwards?() AudioServicesPlaySystemSound(1155) }).minSize(CGSize(width: 38.0, height: 38.0))))) @@ -529,9 +532,10 @@ public final class EntityKeyboardComponent: Component { contentAccessoryLeftButtons: contentAccessoryLeftButtons, contentAccessoryRightButtons: contentAccessoryRightButtons, defaultId: component.defaultToEmojiTab ? "emoji" : "stickers", - contentBackground: AnyComponent(BlurredBackgroundComponent( - color: component.theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75) - )), + contentBackground: nil/*AnyComponent(BlurredBackgroundComponent( + color: component.theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75), + tintContainerView: self.tintContainerView + ))*/, topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent( theme: component.theme, overflowHeight: component.hiddenInputHeight, @@ -542,7 +546,7 @@ public final class EntityKeyboardComponent: Component { theme: component.theme, bottomInset: component.bottomInset, deleteBackwards: { [weak self] in - self?.component?.emojiContent.inputInteraction.deleteBackwards() + self?.component?.emojiContent.inputInteractionHolder.inputInteraction?.deleteBackwards() AudioServicesPlaySystemSound(0x451) } )), diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index c6676fbaf3..7f8c132158 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -213,7 +213,7 @@ public final class GifPagerContentComponent: Component { return true } - public final class View: ContextControllerSourceView, UIScrollViewDelegate { + public final class View: ContextControllerSourceView, PagerContentViewWithBackground, UIScrollViewDelegate { private struct ItemGroupDescription: Equatable { let hasTitle: Bool let itemCount: Int @@ -400,6 +400,8 @@ public final class GifPagerContentComponent: Component { private final class ContentScrollView: UIScrollView, PagerExpandableScrollView { } + private let backgroundView: BlurredBackgroundView + private let shimmerHostView: PortalSourceView private let standaloneShimmerEffect: StandaloneShimmerEffect @@ -418,6 +420,8 @@ public final class GifPagerContentComponent: Component { private var currentLoadMoreToken: String? override init(frame: CGRect) { + self.backgroundView = BlurredBackgroundView(color: nil) + self.shimmerHostView = PortalSourceView() self.standaloneShimmerEffect = StandaloneShimmerEffect() @@ -427,6 +431,8 @@ public final class GifPagerContentComponent: Component { super.init(frame: frame) + self.addSubview(self.backgroundView) + self.shimmerHostView.alpha = 0.0 self.addSubview(self.shimmerHostView) @@ -745,6 +751,15 @@ public final class GifPagerContentComponent: Component { } } + public func pagerUpdateBackground(backgroundFrame: CGRect, transition: Transition) { + guard let theme = self.theme else { + return + } + self.backgroundView.updateColor(color: theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75), 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 { diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index 9f3b56b741..aed0d0e445 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -127,14 +127,14 @@ public final class TextNodeWithEntities { 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 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 itemSize = (font.pointSize * 24.0 / 17.0) * 0.5 let runDelegateData = RunDelegateData( ascent: font.ascender, @@ -230,7 +230,9 @@ public final class TextNodeWithEntities { 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) + 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] { 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 3c45e3b85a280cd97ccc9201e55c8523445fdbb6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 508 zcmVPx$wn;=mR5%fxm9b6(F${)nUl9xpEQp22KtkdP;5|@vg-2*r1PcSGqN1Rq0v0Bo z02bZ|v9XjU!GEh)XyG_&di`I}VdpR)1^c=bE zRw4tLLurqQca4?n$MN{2DR(q_IyBY{iD{picZ{K)AkqLNZc3L;;DEC5KpC40j^kPS zs;~j-7tsYZH-vnx1|Jx_nw0aTKb7=AN3Z zvGyv1&(+YNHzwzW)cdhz#fz#^g}|0000AxPx$`bk7VR9FeMn6Xa7Fc5~%kzirzKv_Y8z5q)lUZ6`Qwu+~Kr3+8M!U9qko}lW6 zl%+3#RH@%S>Q)h*m9;3N zaZ;ixe#1aGz_GX)@TC@D9kUMzr^Nzk0LZlgkvb{#%}@{y0Q3_SA!;Bt2nPVV(ASeC z;yQ4PRT?jchzTMEfOY{91H=cQ0uch@3*dzC0SN)9g^+-Bjt{RFukSZl&hT?t(;IlB zChP#L8D`l^Db=!lO}_~M34jO!gQwH!-s0u$ zacd3e8tI%Io%edZZ}@PG^*9hn@<{$A6A}P3a|uXeCVT*-Ahnws?jy)_4H!|o)iY%6 z&}tz#89>TWglKI5)8~LVA-Dk8UtkrW4FRdtgan|x8~61?#x@{A0wI{Me*xhe0ODoy ziIYS4IF^O&@6vcm>R=1j^(Ao=oDFq4yf-9u5GY#Cs)0V1s5zWg;z?e;6=!{e0|I^L zdjbJN0T2Vm0Rcqi7#Is6r)UOA6Z}7b Signal { + static func emojiInputData(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer) -> 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 { @@ -250,7 +250,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { context: context, animationCache: animationCache, animationRenderer: animationRenderer, - inputInteraction: inputInteraction, + inputInteractionHolder: EmojiPagerContentComponent.InputInteractionHolder(), itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in var hasClear = false if group.id == AnyHashable("recent") { @@ -291,321 +291,6 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } |> distinctUntilChanged - let emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in - let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in - guard 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 { - //TODO:localize - - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", 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: false, action: { _ in return false }), 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: { - }, - addGroupAction: { [weak controllerInteraction] 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.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 { - 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 - ) - let 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) - }, - 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.addStickerPackInteractively(info: featuredEmojiPack.info, items: featuredEmojiPack.topItems).start() - - 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 - ) - let animationCache = AnimationCacheImpl(basePath: context.account.postbox.mediaBox.basePath + "/animation-cache", allocateTempFile: { return TempBox.shared.tempFile(fileName: "file").path }) @@ -616,7 +301,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { animationRenderer = MultiAnimationRendererImpl() //} - let emojiItems = emojiInputData(context: context, inputInteraction: emojiInputInteraction, animationCache: animationCache, animationRenderer: animationRenderer) + let emojiItems = emojiInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer) let stickerNamespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] let stickerOrderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] @@ -863,7 +548,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { context: context, animationCache: animationCache, animationRenderer: animationRenderer, - inputInteraction: stickerInputInteraction, + inputInteractionHolder: EmojiPagerContentComponent.InputInteractionHolder(), itemGroups: itemGroups.map { group -> EmojiPagerContentComponent.ItemGroup in var hasClear = false var isEmbedded = false @@ -1028,6 +713,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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? { @@ -1253,7 +940,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { private let gifComponent = Promise() private var gifInputInteraction: GifPagerContentComponent.InputInteraction? - init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction?) { + fileprivate var emojiInputInteraction: EmojiPagerContentComponent.InputInteraction? + private var stickerInputInteraction: EmojiPagerContentComponent.InputInteraction? + + init(context: AccountContext, currentInputData: InputData, updatedInputData: Signal, defaultToEmojiTab: Bool, controllerInteraction: ChatControllerInteraction?, interfaceInteraction: ChatPanelInterfaceInteraction?, chatPeerId: PeerId?) { self.context = context self.currentInputData = currentInputData self.defaultToEmojiTab = defaultToEmojiTab @@ -1271,6 +961,331 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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 interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in + let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in + guard 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 { + //TODO:localize + + let presentationData = context.sharedContext.currentPresentationData.with { $0 } + controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", 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: false, action: { _ in return false }), 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: { + }, + addGroupAction: { [weak self, weak controllerInteraction] 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.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) + }, + 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, @@ -1295,7 +1310,14 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } if useAnimation { - transition = Transition(animation: .curve(duration: 0.4, curve: .spring)).withUserData(EmojiPagerContentComponent.ContentAnimation(type: .generic)) + 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) @@ -1459,6 +1481,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { gifContent = nil } + stickerContent?.inputInteractionHolder.inputInteraction = self.stickerInputInteraction + self.currentInputData.emoji.inputInteractionHolder.inputInteraction = self.emojiInputInteraction + let entityKeyboardSize = self.entityKeyboardView.update( transition: mappedTransition, component: AnyComponent(EntityKeyboardComponent( @@ -1824,7 +1849,7 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV let semaphore = DispatchSemaphore(value: 0) var emojiComponent: EmojiPagerContentComponent? - let _ = ChatEntityKeyboardInputNode.emojiInputData(context: context, inputInteraction: inputInteraction, animationCache: self.animationCache, animationRenderer: self.animationRenderer).start(next: { value in + let _ = ChatEntityKeyboardInputNode.emojiInputData(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer).start(next: { value in emojiComponent = value semaphore.signal() }) @@ -1841,9 +1866,12 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV ), updatedInputData: .never(), defaultToEmojiTab: true, - controllerInteraction: nil + controllerInteraction: nil, + interfaceInteraction: nil, + chatPeerId: nil ) self.inputNode = inputNode + inputNode.emojiInputInteraction = inputInteraction inputNode.externalTopPanelContainerImpl = nil inputNode.switchToTextInput = { [weak self] in self?.switchToKeyboard?() diff --git a/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift b/submodules/TelegramUI/Sources/ChatMediaInputStickerGridItem.swift index 06bdc56632..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 } diff --git a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift index 2a9c0d613c..c4773edf75 100644 --- a/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageActionItemNode.swift @@ -42,6 +42,24 @@ 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 = TextNodeWithEntities() self.labelNode.textNode.isUserInteractionEnabled = false @@ -340,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 + } } } }) 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/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/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 From e1b4af14616d6fc055f7c20aec99cf18bfd70b5e Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Fri, 22 Jul 2022 17:46:09 +0300 Subject: [PATCH 077/113] Various fixes --- .../AttachmentTextInputPanelNode.swift | 2 +- .../Sources/AttachmentPanel.swift | 1 + .../Sources/BotCheckoutControllerNode.swift | 6 + .../BotCheckoutPaymentMethodSheet.swift | 6 + .../Sources/ChatTextInputPanelState.swift | 27 +-- submodules/ChatSendMessageActionUI/BUILD | 1 + ...ChatSendMessageActionSheetController.swift | 10 +- ...SendMessageActionSheetControllerNode.swift | 25 ++- .../Sources/LottieAnimationComponent.swift | 5 +- .../Display/Source/TooltipController.swift | 6 +- .../Source/TooltipControllerNode.swift | 4 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 11 +- .../Sources/StickerPackEmojisItem.swift | 6 + .../Payments/BotPaymentForm.swift | 22 ++- .../Resources/Animations/anim_botToKey.json | 1 + .../Resources/Animations/anim_keyToBot.json | 1 + .../Resources/Animations/anim_keyToSmile.json | 1 + .../Animations/anim_keyToSticker.json | 1 + .../Resources/Animations/anim_micToVideo.json | 1 + .../Resources/Animations/anim_smileToKey.json | 1 + .../Animations/anim_stickerToKey.json | 1 + .../Resources/Animations/anim_videoToMic.json | 1 + .../TelegramUI/Sources/ChatController.swift | 6 +- .../Sources/ChatInterfaceInputContexts.swift | 12 +- .../ChatTextInputMediaRecordingButton.swift | 124 +++++++++----- .../Sources/ChatTextInputPanelNode.swift | 157 ++++++++++++++---- .../Sources/PeerSelectionControllerNode.swift | 1 + 27 files changed, 329 insertions(+), 111 deletions(-) create mode 100644 submodules/TelegramUI/Resources/Animations/anim_botToKey.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToBot.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToSmile.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToSticker.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_micToVideo.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_smileToKey.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_stickerToKey.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_videoToMic.json diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index 925a02fd84..ae4ea05956 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -322,7 +322,7 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS private var spoilersRevealed = false - private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? + public var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? private let animationCache: AnimationCache private let animationRenderer: MultiAnimationRenderer diff --git a/submodules/AttachmentUI/Sources/AttachmentPanel.swift b/submodules/AttachmentUI/Sources/AttachmentPanel.swift index 996242b0a7..bdc2e56aca 100644 --- a/submodules/AttachmentUI/Sources/AttachmentPanel.swift +++ b/submodules/AttachmentUI/Sources/AttachmentPanel.swift @@ -675,6 +675,7 @@ final class AttachmentPanel: ASDisplayNode, UIScrollViewDelegate { }, schedule: { [weak textInputPanelNode] in textInputPanelNode?.sendMessage(.schedule) }) + controller.emojiViewProvider = textInputPanelNode.emojiViewProvider strongSelf.presentInGlobalOverlay(controller) }, openScheduledMessages: { }, openPeersNearby: { diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index 8941aaccb8..b4417772ec 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -489,6 +489,9 @@ private func availablePaymentMethods(form: BotPaymentForm, current: BotCheckoutP methods.append(.savedCredentials(savedCredentials)) } } + if !form.additionalPaymentMethods.isEmpty { + methods.append(contentsOf: form.additionalPaymentMethods.map { .other($0) }) + } return methods } @@ -1416,6 +1419,9 @@ final class BotCheckoutControllerNode: ItemListControllerNode, PKPaymentAuthoriz } }) return + case let .other(method): + let _ = method + return } } diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift index c3f64e00d4..054c97d2cf 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 } } } @@ -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 { diff --git a/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift b/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift index f973517907..08f5f89fdf 100644 --- a/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift +++ b/submodules/ChatPresentationInterfaceState/Sources/ChatTextInputPanelState.swift @@ -4,18 +4,23 @@ import SwiftSignalKit public enum ChatTextInputAccessoryItem: Equatable { public enum Key: Hashable { - case keyboard - case stickers - case inputButtons + case input + case botInput case commands case silentPost case messageAutoremoveTimeout case scheduledMessages } - case keyboard - case stickers(isEnabled: Bool, isEmoji: Bool) - case inputButtons + 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?) @@ -23,12 +28,10 @@ public enum ChatTextInputAccessoryItem: Equatable { public var key: Key { switch self { - case .keyboard: - return .keyboard - case .stickers: - return .stickers - case .inputButtons: - return .inputButtons + case .input: + return .input + case .botInput: + return .botInput case .commands: return .commands case .silentPost: diff --git a/submodules/ChatSendMessageActionUI/BUILD b/submodules/ChatSendMessageActionUI/BUILD index f78a1da76a..f031506ecc 100644 --- a/submodules/ChatSendMessageActionUI/BUILD +++ b/submodules/ChatSendMessageActionUI/BUILD @@ -19,6 +19,7 @@ swift_library( "//submodules/ChatPresentationInterfaceState:ChatPresentationInterfaceState", "//submodules/ContextUI:ContextUI", "//submodules/AppBundle:AppBundle", + "//submodules/TextFormat:TextFormat", ], visibility = [ "//visibility:public", diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift index 5f2b3d4077..d191144be9 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 @@ -79,13 +82,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, 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 564db9cc8b..8d10ae6b7e 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -9,6 +9,7 @@ import TelegramPresentationData import AccountContext import AppBundle import ContextUI +import TextFormat private let leftInset: CGFloat = 16.0 private let rightInset: CGFloat = 16.0 @@ -158,6 +159,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)? @@ -183,7 +185,7 @@ 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)?) { + init(context: AccountContext, presentationData: PresentationData, reminders: Bool, gesture: ContextGesture, sourceSendButton: ASDisplayNode, textInputNode: EditableTextNode, attachment: Bool, forwardedCount: Int?, hasEntityKeyboard: Bool, send: (() -> Void)?, sendSilently: (() -> Void)?, schedule: (() -> Void)?, cancel: (() -> Void)?) { self.context = context self.presentationData = presentationData self.sourceSendButton = sourceSendButton @@ -191,6 +193,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.textInputNode = textInputNode self.attachment = attachment self.forwardedCount = forwardedCount + self.hasEntityKeyboard = hasEntityKeyboard self.send = send self.cancel = cancel @@ -422,7 +425,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 @@ -531,7 +538,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 +600,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 diff --git a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift index df3e9b90a5..299339653d 100644 --- a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift +++ b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift @@ -143,6 +143,7 @@ public final class LottieAnimationComponent: Component { } strongSelf.didPlayToCompletion = true let _ = strongSelf.update(component: component, availableSize: availableSize, transition: transition) + strongSelf.currentCompletion = nil } animationView.loopMode = .playOnce } else { @@ -175,10 +176,10 @@ public final class LottieAnimationComponent: Component { updatePlayback = true } } + } else { + self.component = component } - 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" }) { 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/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 2dc3ae0916..1a8ebf6a09 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -373,8 +373,17 @@ private final class GiftComponent: CombinedComponent { ) 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: size.height / 2.0)) + .position(CGPoint(x: context.availableSize.width - insets.right - label.size.width / 2.0, y: labelOriginY)) ) context.add(check diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift index 2b5a4c4404..41773c8e84 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -348,6 +348,12 @@ final class StickerPackEmojisItemNode: GridItemNode { 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() { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift index 547c67571f..68acf4a4eb 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift @@ -120,6 +120,21 @@ public struct BotPaymentForm : Equatable { public let nativeProvider: BotPaymentNativeProvider? public let savedInfo: BotPaymentRequestedInfo? 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 { @@ -270,8 +285,7 @@ func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, source: B let _ = title let _ = description let _ = photo - let _ = additionalMethods - + var peers: [Peer] = [] for user in apiUsers { let parsed = TelegramUser(user: user) @@ -297,7 +311,9 @@ func _internal_fetchBotPaymentForm(postbox: Postbox, network: Network, source: B parsedSavedCredentials = .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/TelegramUI/Resources/Animations/anim_botToKey.json b/submodules/TelegramUI/Resources/Animations/anim_botToKey.json new file mode 100644 index 0000000000..d08ff0f116 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/anim_keyToBot.json b/submodules/TelegramUI/Resources/Animations/anim_keyToBot.json new file mode 100644 index 0000000000..0037c39c0d --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/anim_keyToSmile.json b/submodules/TelegramUI/Resources/Animations/anim_keyToSmile.json new file mode 100644 index 0000000000..644e916a01 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/anim_keyToSticker.json b/submodules/TelegramUI/Resources/Animations/anim_keyToSticker.json new file mode 100644 index 0000000000..6e4c44cd25 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/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_smileToKey.json b/submodules/TelegramUI/Resources/Animations/anim_smileToKey.json new file mode 100644 index 0000000000..3197e866b1 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/anim_stickerToKey.json b/submodules/TelegramUI/Resources/Animations/anim_stickerToKey.json new file mode 100644 index 0000000000..ce92cd33da --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/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/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index ab34e8964d..954c65cf04 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1127,6 +1127,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let packReference = packReferences.first, let strongSelf = self else { return } + strongSelf.chatDisplayNode.dismissTextInput() let controller = StickerPackScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, mainStickerPack: packReference, stickerPacks: Array(packReferences), parentNavigationController: strongSelf.effectiveNavigationController) strongSelf.present(controller, in: .window(.root)) } @@ -8446,6 +8447,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)) @@ -15526,7 +15528,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 { @@ -15547,7 +15549,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 { diff --git a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift index 584cbc54fa..788133b528 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceInputContexts.swift @@ -314,13 +314,13 @@ 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 { - accessoryItems.append(.stickers(isEnabled: true, isEmoji: true)) + accessoryItems.append(.input(isEnabled: true, inputMode: .emoji)) return ChatTextInputPanelState(accessoryItems: accessoryItems, contextPlaceholder: contextPlaceholder, mediaRecordingState: chatPresentationInterfaceState.inputTextPanelState.mediaRecordingState) } else { @@ -371,13 +371,13 @@ func inputTextPanelStateForChatPresentationInterfaceState(_ chatPresentationInte } if stickersEnabled { - accessoryItems.append(.stickers(isEnabled: true, isEmoji: stickersAreEmoji)) + accessoryItems.append(.input(isEnabled: true, inputMode: stickersAreEmoji ? .emoji : .stickers)) } else { - accessoryItems.append(.stickers(isEnabled: true, isEmoji: true)) + accessoryItems.append(.input(isEnabled: true, inputMode: .emoji)) } 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/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift index 0c72039bfb..528e41f726 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 + } + + let _ = animationView.update( + transition: .immediate, + component: AnyComponent(LottieAnimationComponent( + animation: LottieAnimationComponent.AnimationItem( + name: animationName, + mode: animationMode + ), + colors: colors, + size: animationFrame.size + )), + environment: {}, + containerSize: animationFrame.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 = 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,8 @@ 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) + self.animationView.view?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) + self.animationView.view?.layer.animateScale(from: 1.0, to: 0.3, duration: 0.15, removeOnCompletion: false) } override func animateOut(_ toSmallSize: Bool) { @@ -480,8 +510,8 @@ 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) + self.animationView.view?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, removeOnCompletion: false) + self.animationView.view?.layer.animateScale(from: 0.3, to: 1.0, duration: 0.15, removeOnCompletion: false) } } @@ -490,8 +520,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 f021309a7f..187633ea18 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -59,9 +59,12 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.iconImageNode.isUserInteractionEnabled = false self.addSubnode(self.iconImageNode) - if case .stickers = item { - self.iconImageNode.isHidden = true - self.animationView = ComponentView() + switch item { + case .input, .botInput: + self.iconImageNode.isHidden = true + self.animationView = ComponentView() + default: + break } if let text = text { @@ -116,12 +119,15 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { 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): @@ -143,7 +149,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { static func calculateWidth(item: ChatTextInputAccessoryItem, image: UIImage?, text: String?, strings: PresentationStrings) -> CGFloat { switch item { - case .keyboard, .stickers, .inputButtons, .silentPost, .commands, .scheduledMessages: + case .input, .botInput, .silentPost, .commands, .scheduledMessages: return 32.0 case let .messageAutoremoveTimeout(timeout): var imageWidth = (image?.size.width ?? 0.0) + CGFloat(8.0) @@ -156,6 +162,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { } func updateLayout(item: ChatTextInputAccessoryItem, size: CGSize) { + let previousItem = self.item self.item = item if let image = self.iconImageNode.image { @@ -165,26 +172,112 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { 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.iconImageNode.frame = imageFrame - if case let .stickers(_, isEmoji) = item, let animationView = self.animationView { + if let animationView = self.animationView { let animationFrame = imageFrame.insetBy(dx: -4.0, dy: -4.0) - var colors: [String: UIColor] = [:] - let colorKeys: [String] = [ + 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" ] + + var colorKeys: [String] = ["__allcolors__"] + let animationName: String + var animationMode: LottieAnimationComponent.AnimationItem.Mode = .still(position: .end) + if let inputMode = inputMode { + switch inputMode { + case .keyboard: + if let previousInputMode = previousInputMode { + if case .stickers = previousInputMode { + animationName = "anim_stickerToKey" + animationMode = .animating(loop: false) + } else if case .emoji = previousInputMode { + animationName = "anim_smileToKey" + animationMode = .animating(loop: false) + } else if case .bot = previousInputMode { + animationName = "anim_botToKey" + animationMode = .animating(loop: false) + } else { + animationName = "anim_stickerToKey" + } + } else { + animationName = "anim_stickerToKey" + } + case .stickers: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "anim_keyToSticker" + animationMode = .animating(loop: false) + } else if case .emoji = previousInputMode { + animationName = "anim_smileToSticker" + animationMode = .animating(loop: false) + colorKeys = emojiColorKeys + } else { + animationName = "anim_keyToSticker" + } + } else { + animationName = "anim_keyToSticker" + } + case .emoji: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "anim_keyToSmile" + animationMode = .animating(loop: false) + } else if case .stickers = previousInputMode { + animationName = "anim_stickerToSmile" + animationMode = .animating(loop: false) + colorKeys = emojiColorKeys + } else { + animationName = "anim_keyToSmile" + } + } else { + animationName = "anim_keyToSmile" + } + case .bot: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "anim_keyToBot" + animationMode = .animating(loop: false) + } else { + animationName = "anim_keyToBot" + } + } else { + animationName = "anim_keyToBot" + } + } + } else { + animationName = "" + } + + var colors: [String: UIColor] = [:] for colorKey in colorKeys { colors[colorKey] = self.theme.chat.inputPanel.inputControlColor } + let _ = animationView.update( transition: .immediate, component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( - name: !isEmoji ? "anim_stickertosmile" : "anim_smiletosticker", - mode: .animateTransitionFromPrevious + name: animationName, + mode: animationMode ), colors: colors, size: animationFrame.size @@ -193,6 +286,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { containerSize: animationFrame.size ) if let view = animationView.view { + view.isUserInteractionEnabled = false if view.superview == nil { self.view.addSubview(view) } @@ -586,7 +680,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { private var touchDownGestureRecognizer: TouchDownGestureRecognizer? - private var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? + var emojiViewProvider: ((ChatTextInputTextCustomEmojiAttribute) -> UIView)? init(presentationInterfaceState: ChatPresentationInterfaceState, presentationContext: ChatPresentationContext?, presentController: @escaping (ViewController) -> Void) { self.presentationInterfaceState = presentationInterfaceState @@ -2942,20 +3036,23 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { 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 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 .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) @@ -3011,7 +3108,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/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index 6693d99a67..ac30fa69f4 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -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: { From 61b47ada275ce694009c8e673d84e19cbd0bb642 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Fri, 22 Jul 2022 23:30:46 +0200 Subject: [PATCH 078/113] Emoji improvements --- .../Sources/VideoStickerFrameSource.swift | 8 +- .../FFMpegMediaVideoFrameDecoder.swift | 8 +- .../Sources/SoftwareVideoSource.swift | 6 +- .../Postbox/Sources/MessageHistoryTable.swift | 3 + .../Postbox/Sources/MessageMediaTable.swift | 4 + submodules/Postbox/Sources/Postbox.swift | 20 +++ .../SoftwareVideoLayerFrameManager.swift | 2 +- .../Sources/AnimatedStickerUtils.swift | 2 +- .../State/AccountStateManagementUtils.swift | 51 +++++- .../Sources/State/FetchChatList.swift | 5 +- .../TelegramCore/Sources/State/Holes.swift | 77 ++++++++- .../Sources/AnimationCache.swift | 16 +- .../AnimationCache/Sources/ImageData.swift | 6 +- .../Sources/EmojiPagerContentComponent.swift | 163 +++++++++--------- .../Sources/EntityKeyboard.swift | 2 +- .../EntityKeyboardTopPanelComponent.swift | 15 +- .../Sources/TextNodeWithEntities.swift | 4 +- .../Sources/VideoAnimationCache.swift | 2 +- .../Sources/ChatControllerNode.swift | 2 +- .../Sources/ChatEntityKeyboardInputNode.swift | 59 ++++--- .../ChatInterfaceStateAccessoryPanels.swift | 2 +- .../ChatInterfaceStateInputPanels.swift | 2 +- .../ChatMessageAttachedContentNode.swift | 78 ++++++--- ...entLogPreviousDescriptionContentNode.swift | 8 +- ...ssageEventLogPreviousLinkContentNode.swift | 8 +- ...geEventLogPreviousMessageContentNode.swift | 8 +- .../ChatMessageGameBubbleContentNode.swift | 4 +- .../ChatMessageInvoiceBubbleContentNode.swift | 2 +- .../Sources/ChatMessageNotificationItem.swift | 46 ++++- .../ChatMessageWebpageBubbleContentNode.swift | 2 +- .../Sources/ChatTextInputPanelNode.swift | 10 +- .../Sources/EditAccessoryPanelNode.swift | 55 +++++- .../PublicHeaders/YuvConversion/YUV.h | 2 +- submodules/YuvConversion/Sources/YUV.m | 8 +- 34 files changed, 484 insertions(+), 206 deletions(-) diff --git a/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift b/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift index 2038bbed6c..93eb8c659b 100644 --- a/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift +++ b/submodules/AnimatedStickerNode/Sources/VideoStickerFrameSource.swift @@ -272,8 +272,8 @@ private final class VideoStickerFrameSourceCache { private let useCache = true -public func makeVideoStickerDirectFrameSource(queue: Queue, path: String, width: Int, height: Int, cachePathPrefix: String?) -> AnimatedStickerFrameSource? { - return VideoStickerDirectFrameSource(queue: queue, path: path, width: width, height: height, cachePathPrefix: cachePathPrefix) +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 { @@ -293,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 @@ -310,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/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/Postbox/Sources/MessageHistoryTable.swift b/submodules/Postbox/Sources/MessageHistoryTable.swift index 30f277299e..57689a4d46 100644 --- a/submodules/Postbox/Sources/MessageHistoryTable.swift +++ b/submodules/Postbox/Sources/MessageHistoryTable.swift @@ -2537,6 +2537,9 @@ final class MessageHistoryTable: Table { } for mediaId in attribute.associatedMediaIds { if associatedMedia[mediaId] == nil { + if mediaId.id == 5364107552168613887 { + assert(true) + } if let media = self.getMedia(mediaId) { associatedMedia[mediaId] = media } diff --git a/submodules/Postbox/Sources/MessageMediaTable.swift b/submodules/Postbox/Sources/MessageMediaTable.swift index 70bb530632..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 diff --git a/submodules/Postbox/Sources/Postbox.swift b/submodules/Postbox/Sources/Postbox.swift index 105cc1eab1..1af2ada131 100644 --- a/submodules/Postbox/Sources/Postbox.swift +++ b/submodules/Postbox/Sources/Postbox.swift @@ -740,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) @@ -2352,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/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift b/submodules/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift index fd3ab89d89..0e7d528b9f 100644 --- a/submodules/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift +++ b/submodules/SoftwareVideo/Sources/SoftwareVideoLayerFrameManager.swift @@ -116,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)) } })) } 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/TelegramCore/Sources/State/AccountStateManagementUtils.swift b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift index b6412810b3..f8f3b3b666 100644 --- a/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift +++ b/submodules/TelegramCore/Sources/State/AccountStateManagementUtils.swift @@ -1556,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) } @@ -1589,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 @@ -1599,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 @@ -1642,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 { @@ -1663,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) + } } } @@ -1825,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 @@ -1879,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 @@ -1900,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) { @@ -2052,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) } 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/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 8093e31732..081ab6a77e 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -235,10 +235,12 @@ private final class AnimationCacheItemWriterInternal { private var frames: [FrameMetadata] = [] - private let dctQuality: Int + private let dctQualityLuma: Int + private let dctQualityChroma: Int init?(allocateTempFile: @escaping () -> String) { - self.dctQuality = 70 + self.dctQualityLuma = 70 + self.dctQualityChroma = 75 self.compressedPath = allocateTempFile() @@ -297,7 +299,7 @@ private final class AnimationCacheItemWriterInternal { if let current = self.currentDctData { dctData = current } else { - dctData = DctData(generatingTablesAtQuality: self.dctQuality) + dctData = DctData(generatingTablesAtQualityLuma: self.dctQualityLuma, chroma: self.dctQualityChroma) self.currentDctData = dctData } @@ -433,12 +435,14 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { private var frames: [FrameMetadata] = [] - private let dctQuality: Int + private let dctQualityLuma: Int + private let dctQualityChroma: Int private let lock = Lock() init?(queue: Queue, allocateTempFile: @escaping () -> String, completion: @escaping (CompressedResult?) -> Void) { - self.dctQuality = 70 + self.dctQualityLuma = 70 + self.dctQualityChroma = 75 self.queue = queue self.compressedPath = allocateTempFile() @@ -511,7 +515,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { if let current = self.currentDctData { dctData = current } else { - dctData = DctData(generatingTablesAtQuality: self.dctQuality) + dctData = DctData(generatingTablesAtQualityLuma: self.dctQualityLuma, chroma: self.dctQualityChroma) self.currentDctData = dctData } diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift index 1c833fc60e..a0caff07c1 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/ImageData.swift @@ -173,11 +173,11 @@ final class DctData { self.chromaDct = ImageDCT(table: chromaTableData) } - init(generatingTablesAtQuality quality: Int) { - self.lumaTable = ImageDCTTable(quality: quality, isChroma: false) + init(generatingTablesAtQualityLuma lumaQuality: Int, chroma chromaQuality: Int) { + self.lumaTable = ImageDCTTable(quality: lumaQuality, isChroma: false) self.lumaDct = ImageDCT(table: self.lumaTable) - self.chromaTable = ImageDCTTable(quality: quality, isChroma: true) + self.chromaTable = ImageDCTTable(quality: chromaQuality, isChroma: true) self.chromaDct = ImageDCT(table: self.chromaTable) } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 75ee7ec788..97ad8548ab 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -599,7 +599,8 @@ private final class GroupHeaderLayer: UIView { color = theme.chat.inputPanel.primaryTextColor needsTintText = false } else { - color = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1) + //color = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1) + color = UIColor(white: 1.0, alpha: 0.0) needsTintText = true } let subtitleColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1) @@ -1520,6 +1521,7 @@ public final class EmojiPagerContentComponent: Component { var itemFeaturedHeaderHeight: CGFloat var nativeItemSize: CGFloat let visibleItemSize: CGFloat + let playbackItemSize: CGFloat var horizontalSpacing: CGFloat var verticalSpacing: CGFloat var verticalGroupDefaultSpacing: CGFloat @@ -1543,6 +1545,7 @@ public final class EmojiPagerContentComponent: Component { case .compact: minItemsPerRow = 8 self.nativeItemSize = 36.0 + self.playbackItemSize = 48.0 self.verticalSpacing = 9.0 minSpacing = 9.0 self.itemDefaultHeaderHeight = 24.0 @@ -1552,6 +1555,7 @@ public final class EmojiPagerContentComponent: Component { case .detailed: minItemsPerRow = 5 self.nativeItemSize = 71.0 + self.playbackItemSize = 96.0 self.verticalSpacing = 2.0 minSpacing = 12.0 self.itemDefaultHeaderHeight = 24.0 @@ -1820,79 +1824,59 @@ public final class EmojiPagerContentComponent: Component { super.init() if let file = file { - if file.isAnimatedSticker || file.isVideoEmoji { - 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 { - 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() - } - }) + let loadAnimation: () -> Void = { [weak self] in + guard let strongSelf = self else { + return } - if attemptSynchronousLoad { - if !renderer.loadFirstFrameSynchronously(target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize) { - self.updateDisplayPlaceholder(displayPlaceholder: true) - } + 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) - loadAnimation() - } else { - let _ = renderer.loadFirstFrame(target: self, cache: cache, itemId: file.resource.id.stringRepresentation, size: pixelSize, completion: { [weak self] success in - loadAnimation() + let dataDisposable = source.directDataPath(attemptSynchronously: false).start(next: { result in + guard let result = result else { + return + } - if !success { - guard let strongSelf = self else { + if file.isVideoEmoji { + 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 } - - strongSelf.updateDisplayPlaceholder(displayPlaceholder: true) + 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) } }) - } - } else if let _ = file.dimensions { - let isSmall: Bool = false - self.disposable = (chatMessageSticker(account: context.account, file: file, small: isSmall, synchronousLoad: attemptSynchronousLoad)).start(next: { [weak self] resultTransform in - let boundingSize = CGSize(width: 93.0, height: 93.0) - let imageSize = boundingSize//dimensions.cgSize.aspectFitted(boundingSize) - if let image = resultTransform(TransformImageArguments(corners: ImageCorners(), imageSize: imageSize, boundingSize: boundingSize, intrinsicInsets: UIEdgeInsets(), resizeMode: .fill(.clear)))?.generateImage() { - Queue.mainQueue().async { - guard let strongSelf = self else { - return - } - - strongSelf.contents = image.cgImage - } + 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) + } - self.fetchDisposable = freeMediaFileResourceInteractiveFetched(account: context.account, fileReference: stickerPackFileReference(file), resource: chatMessageStickerResource(file: file, small: isSmall)).start() + 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 @@ -1907,7 +1891,7 @@ public final class EmojiPagerContentComponent: Component { 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: (scaledSize.width - boundingRect.width) / 2.0 + boundingRect.minX, y: (scaledSize.height - boundingRect.height) / 2.0 + boundingRect.minY)) + 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 @@ -2120,8 +2104,8 @@ public final class EmojiPagerContentComponent: Component { } } - private let shimmerHostView: PortalSourceView - private let standaloneShimmerEffect: StandaloneShimmerEffect + private let shimmerHostView: PortalSourceView? + private let standaloneShimmerEffect: StandaloneShimmerEffect? private let backgroundView: BlurredBackgroundView private var vibrancyEffectView: UIVisualEffectView? @@ -2155,8 +2139,13 @@ public final class EmojiPagerContentComponent: Component { override init(frame: CGRect) { self.backgroundView = BlurredBackgroundView(color: nil) - self.shimmerHostView = PortalSourceView() - self.standaloneShimmerEffect = StandaloneShimmerEffect() + if ProcessInfo.processInfo.activeProcessorCount > 2 { + self.shimmerHostView = PortalSourceView() + self.standaloneShimmerEffect = StandaloneShimmerEffect() + } else { + self.shimmerHostView = nil + self.standaloneShimmerEffect = nil + } self.mirrorContentScrollView = UIView() self.mirrorContentScrollView.layer.anchorPoint = CGPoint() @@ -2170,13 +2159,15 @@ public final class EmojiPagerContentComponent: Component { self.addSubview(self.backgroundView) - self.shimmerHostView.alpha = 0.0 - self.addSubview(self.shimmerHostView) + 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?.standaloneShimmerEffect?.updateLayer() } self.scrollView.delaysContentTouches = false @@ -3304,6 +3295,7 @@ public final class EmojiPagerContentComponent: Component { } let itemNativeFitSize = itemDimensions.fitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) + let itemPlaybackSize = itemDimensions.fitted(CGSize(width: itemLayout.playbackItemSize, height: itemLayout.playbackItemSize)) var animateItemIn = false var updateItemLayerPlaceholder = false @@ -3326,7 +3318,7 @@ public final class EmojiPagerContentComponent: Component { renderer: component.animationRenderer, placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), - pointSize: itemVisibleFitSize, + pointSize: item.staticEmoji == nil ? itemPlaybackSize : itemVisibleFitSize, onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { return @@ -3525,10 +3517,12 @@ public final class EmojiPagerContentComponent: Component { } private func updateShimmerIfNeeded() { - if self.placeholdersContainerView.subviews.isEmpty { - self.standaloneShimmerEffect.layer = nil - } else { - self.standaloneShimmerEffect.layer = self.shimmerHostView.layer + if let standaloneShimmerEffect = self.standaloneShimmerEffect, let shimmerHostView = self.shimmerHostView { + if self.placeholdersContainerView.subviews.isEmpty { + standaloneShimmerEffect.layer = nil + } else { + standaloneShimmerEffect.layer = shimmerHostView.layer + } } } @@ -3544,11 +3538,16 @@ public final class EmojiPagerContentComponent: Component { } if self.vibrancyEffectView == nil { - let blurEffect = UIBlurEffect(style: .extraLight) + 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) } @@ -3577,11 +3576,15 @@ public final class EmojiPagerContentComponent: Component { self.pagerEnvironment = pagerEnvironment - transition.setFrame(view: self.shimmerHostView, frame: CGRect(origin: CGPoint(), size: availableSize)) + if let shimmerHostView = self.shimmerHostView { + transition.setFrame(view: 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) + 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]? diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 3bc5e874cd..440c3a4787 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -449,7 +449,7 @@ public final class EntityKeyboardComponent: Component { if let file = itemGroup.items[0].file { topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.supergroupId, - isReorderable: true, + isReorderable: !itemGroup.isFeatured, content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( context: component.emojiContent.context, file: file, diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 1921cbb023..5d6506e888 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -1449,6 +1449,8 @@ final class EntityKeyboardTopPanelComponent: Component { visibleBounds.origin.x -= 200.0 visibleBounds.size.width += 400.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 { @@ -1477,10 +1479,10 @@ final class EntityKeyboardTopPanelComponent: Component { 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) - /*if index == visibleItemRange.minIndex, !itemTransition.animation.isImmediate { - print("\(index): \(itemView.frame) -> \(itemFrame)") - }*/ 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] = [] @@ -1804,6 +1806,13 @@ final class EntityKeyboardTopPanelComponent: Component { 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 { diff --git a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift index aed0d0e445..8ffe7cf143 100644 --- a/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift +++ b/submodules/TelegramUI/Components/TextNodeWithEntities/Sources/TextNodeWithEntities.swift @@ -127,14 +127,14 @@ public final class TextNodeWithEntities { 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 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) * 0.5 + let itemSize = (font.pointSize * 24.0 / 17.0) let runDelegateData = RunDelegateData( ascent: font.ascender, diff --git a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift index c59db57746..80190fc36f 100644 --- a/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift +++ b/submodules/TelegramUI/Components/VideoAnimationCache/Sources/VideoAnimationCache.swift @@ -20,7 +20,7 @@ private func roundUp(_ numToRound: Int, multiple: Int) -> Int { 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) else { + 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) diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 5503ea1c4b..775821121c 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -560,7 +560,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { 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 diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index bc20d3b0d1..6decb7096e 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -86,7 +86,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - static func emojiInputData(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer) -> Signal { + static func emojiInputData(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, isStandalone: 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 { @@ -218,29 +218,31 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - 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 { + if !isStandalone { + for featuredEmojiPack in featuredEmojiPacks { + if installedCollectionIds.contains(featuredEmojiPack.info.id) { 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])) + + 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])) + } } } } @@ -301,7 +303,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { animationRenderer = MultiAnimationRendererImpl() //} - let emojiItems = emojiInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer) + let emojiItems = emojiInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer, isStandalone: false) let stickerNamespaces: [ItemCollectionId.Namespace] = [Namespaces.ItemCollection.CloudStickerPacks] let stickerOrderedItemListCollectionIds: [Int32] = [Namespaces.OrderedItemList.CloudSavedStickers, Namespaces.OrderedItemList.CloudRecentStickers, Namespaces.OrderedItemList.PremiumStickers, Namespaces.OrderedItemList.CloudPremiumStickers] @@ -1484,6 +1486,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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( @@ -1559,6 +1563,13 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { ) 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) } @@ -1849,7 +1860,7 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV let semaphore = DispatchSemaphore(value: 0) var emojiComponent: EmojiPagerContentComponent? - let _ = ChatEntityKeyboardInputNode.emojiInputData(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer).start(next: { value in + let _ = ChatEntityKeyboardInputNode.emojiInputData(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, isStandalone: true).start(next: { value in emojiComponent = value semaphore.signal() }) diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift index f56092af6e..a0a8432548 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift @@ -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 } 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/ChatMessageAttachedContentNode.swift b/submodules/TelegramUI/Sources/ChatMessageAttachedContentNode.swift index ed841436f1..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 { @@ -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/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/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/ChatMessageNotificationItem.swift b/submodules/TelegramUI/Sources/ChatMessageNotificationItem.swift index 06cecfc2fd..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,6 +204,8 @@ 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 } @@ -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/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/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index f021309a7f..d0c9788f9c 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -588,7 +588,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { private 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 @@ -652,6 +652,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { super.init() + self.context = context + self.addSubnode(self.clippingNode) self.sendAsAvatarContainerNode.activated = { [weak self] gesture, _ in @@ -1109,9 +1111,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] diff --git a/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift b/submodules/TelegramUI/Sources/EditAccessoryPanelNode.swift index 70af8117f2..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] @@ -238,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 { @@ -247,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 @@ -268,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)" @@ -325,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/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) { From 3e8fe53f472596667671911591d23be23b5d392f Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sat, 23 Jul 2022 00:47:07 +0200 Subject: [PATCH 079/113] Adjust DCT quality --- .../Components/AnimationCache/Sources/AnimationCache.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 081ab6a77e..59a51609cc 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -240,7 +240,7 @@ private final class AnimationCacheItemWriterInternal { init?(allocateTempFile: @escaping () -> String) { self.dctQualityLuma = 70 - self.dctQualityChroma = 75 + self.dctQualityChroma = 88 self.compressedPath = allocateTempFile() @@ -442,7 +442,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { init?(queue: Queue, allocateTempFile: @escaping () -> String, completion: @escaping (CompressedResult?) -> Void) { self.dctQualityLuma = 70 - self.dctQualityChroma = 75 + self.dctQualityChroma = 88 self.queue = queue self.compressedPath = allocateTempFile() From 75399409682872158942bf5ec41a823a2874b21f Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sat, 23 Jul 2022 14:39:30 +0300 Subject: [PATCH 080/113] Various fixes --- .../Sources/BotCheckoutControllerNode.swift | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index b4417772ec..881b4467a4 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -476,13 +476,10 @@ 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) - } - if let current = current { - if !methods.contains(current) { - methods.append(current) - } + hasApplePay = true } if let savedCredentials = form.savedCredentials { if !methods.contains(.savedCredentials(savedCredentials)) { @@ -492,6 +489,11 @@ private func availablePaymentMethods(form: BotPaymentForm, current: BotCheckoutP if !form.additionalPaymentMethods.isEmpty { methods.append(contentsOf: form.additionalPaymentMethods.map { .other($0) }) } + if let current = current { + if !methods.contains(current) { + methods.insert(current, at: hasApplePay ? 1 : 0) + } + } return methods } @@ -1284,6 +1286,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 @@ -1467,9 +1485,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 @@ -1484,19 +1499,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): From 68f93cc7487cf229ad9f88291c2d9b09b1ff3791 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 24 Jul 2022 01:09:15 +0300 Subject: [PATCH 081/113] Various fixes --- .../Sources/ContextActionsContainerNode.swift | 59 ++++++++++++++++--- .../ContextControllerActionsStackNode.swift | 7 +++ .../ChatTextInputMediaRecordingButton.swift | 2 +- 3 files changed, 60 insertions(+), 8 deletions(-) diff --git a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift index c7507f66c9..8c0697bdcc 100644 --- a/submodules/ContextUI/Sources/ContextActionsContainerNode.swift +++ b/submodules/ContextUI/Sources/ContextActionsContainerNode.swift @@ -356,6 +356,8 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { private var file: TelegramMediaFile? private let targetSelectionIndex: Int? + private var hapticFeedback: HapticFeedback? + private var action: (() -> Void)? var requestDismiss: (@escaping () -> Void) -> Void = { _ in } @@ -442,13 +444,7 @@ final class InnerTextSelectionTipContainerNode: ASDisplayNode { guard let strongSelf = self else { return } - if highlighted { - strongSelf.highlightBackgroundNode.alpha = 1.0 - } else { - let previousAlpha = strongSelf.highlightBackgroundNode.alpha - strongSelf.highlightBackgroundNode.alpha = 0.0 - strongSelf.highlightBackgroundNode.layer.animateAlpha(from: previousAlpha, to: 0.0, duration: 0.2) - } + strongSelf.updateHighlight(animated: true) } self.buttonNode.addTarget(self, action: #selector(self.pressed), forControlEvents: .touchUpInside) @@ -595,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 { diff --git a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift index e4e72f488a..26ea4f0131 100644 --- a/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift +++ b/submodules/ContextUI/Sources/ContextControllerActionsStackNode.swift @@ -912,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) } } diff --git a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift index 528e41f726..99e4897580 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift @@ -379,7 +379,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto environment: {}, containerSize: animationFrame.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 = animationView.view { view.isUserInteractionEnabled = false if view.superview == nil { From 3347f0514e317feaef20afe1d66c187005db253e Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 03:15:19 +0200 Subject: [PATCH 082/113] Emoji improvements --- .../Sources/LottieAnimationComponent.swift | 11 +- .../Sources/PagerComponent.swift | 33 +- submodules/Display/Source/UIKitUtils.swift | 2 +- .../DefaultDarkPresentationTheme.swift | 5 +- .../DefaultDarkTintedPresentationTheme.swift | 10 +- .../Sources/DefaultDayPresentationTheme.swift | 5 +- .../Sources/PresentationTheme.swift | 12 +- .../Sources/PresentationThemeCodable.swift | 30 +- .../Sources/AnimationCache.swift | 6 +- .../Sources/EmojiPagerContentComponent.swift | 81 ++-- .../Sources/EntityKeyboard.swift | 70 +-- .../EntityKeyboardBottomPanelComponent.swift | 83 +++- ...tyKeyboardTopContainerPanelComponent.swift | 2 +- .../EntityKeyboardTopPanelComponent.swift | 208 ++++++--- .../Sources/GifPagerContentComponent.swift | 2 +- .../Sources/LottieAnimationCache.swift | 2 +- .../Sources/MultiAnimationMetalRenderer.swift | 2 +- .../Sources/MultiAnimationRenderer.swift | 12 +- .../Contents.json | 5 +- .../backspace_24.svg | 5 + .../ic_clear.pdf | 107 ----- .../Contents.json | 5 +- .../EntityInputEmojiIcon.imageset/emoji.svg | 6 + .../ic_emoji.pdf | 123 ----- .../Contents.json | 5 +- .../EntityInputGifsIcon.imageset/gifs.svg | 7 + .../EntityInputGifsIcon.imageset/ic_gifs.pdf | 128 ------ .../Contents.json | 5 +- .../keyboard_24.svg | 8 + .../EntityInputGlobeIcon.imageset/planet.pdf | 255 ----------- .../Contents.json | 5 +- .../ic_search.pdf | 82 ---- .../search_24.svg | 3 + .../Contents.json | 3 + .../Contents.json | 5 +- .../ic_stickers.pdf | 431 ------------------ .../stickers_24.svg | 7 + .../PanelFeaturedIcon.imageset/Contents.json | 15 + .../trending_24.svg | 3 + .../PanelRecentIcon.imageset/Contents.json | 15 + .../PanelRecentIcon.imageset/recent_24.svg | 3 + .../PanelSavedIcon.imageset/Contents.json | 15 + .../PanelSavedIcon.imageset/favourites_24.svg | 3 + .../PanelTrendingIcon.imageset/Contents.json | 15 + .../trendinggifs_24.svg | 3 + .../Sources/ChatControllerNode.swift | 2 +- .../Sources/ChatEntityKeyboardInputNode.swift | 24 +- .../Sources/ChatTextInputPanelNode.swift | 2 +- .../Sources/WallpaperBackgroundNode.swift | 22 +- 49 files changed, 569 insertions(+), 1324 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/backspace_24.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/ic_clear.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/emoji.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/ic_emoji.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/gifs.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/ic_gifs.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/keyboard_24.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/planet.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/ic_search.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/search_24.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/ic_stickers.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/stickers_24.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/trending_24.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/recent_24.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_24.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24.svg diff --git a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift index df3e9b90a5..ea7b60c4dd 100644 --- a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift +++ b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift @@ -127,9 +127,13 @@ public final class LottieAnimationComponent: Component { 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?() } @@ -172,12 +176,15 @@ public final class LottieAnimationComponent: Component { self.animationView = view self.addSubview(view) + animateSize = false updatePlayback = true } } } - self.component = component + if updateComponent { + self.component = component + } if updateColors, let animationView = self.animationView { if let value = component.colors["__allcolors__"] { @@ -208,7 +215,7 @@ public final class LottieAnimationComponent: Component { 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 && !animationView.frame.isEmpty && animationView.frame.size != animationFrame.size { + if !transition.animation.isImmediate && animateSize && !animationView.frame.isEmpty && animationView.frame.size != animationFrame.size { let previouosAnimationFrame = animationView.frame if let snapshotView = animationView.snapshotView(afterScreenUpdates: false) { diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index a042fd5b3b..a020e249f8 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -65,7 +65,7 @@ public final class PagerComponentChildEnvironment: Equatable { public final class PagerComponentPanelEnvironment: Equatable { public let contentOffset: CGFloat public let contentTopPanels: [AnyComponentWithIdentity] - public let contentIcons: [AnyComponentWithIdentity] + public let contentIcons: [PagerComponentContentIcon] public let contentAccessoryLeftButtons: [AnyComponentWithIdentity] public let contentAccessoryRightButtons: [AnyComponentWithIdentity] public let activeContentId: AnyHashable? @@ -76,7 +76,7 @@ public final class PagerComponentPanelEnvironment: Equatabl init( contentOffset: CGFloat, contentTopPanels: [AnyComponentWithIdentity], - contentIcons: [AnyComponentWithIdentity], + contentIcons: [PagerComponentContentIcon], contentAccessoryLeftButtons: [AnyComponentWithIdentity], contentAccessoryRightButtons: [AnyComponentWithIdentity], activeContentId: AnyHashable?, @@ -141,13 +141,36 @@ public enum PagerComponentPanelHideBehavior { 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: [AnyComponentWithIdentity] + public let contentIcons: [PagerComponentContentIcon] public let contentAccessoryLeftButtons:[AnyComponentWithIdentity] public let contentAccessoryRightButtons:[AnyComponentWithIdentity] public let defaultId: AnyHashable? @@ -163,7 +186,7 @@ public final class PagerComponent], contentTopPanels: [AnyComponentWithIdentity], - contentIcons: [AnyComponentWithIdentity], + contentIcons: [PagerComponentContentIcon], contentAccessoryLeftButtons: [AnyComponentWithIdentity], contentAccessoryRightButtons: [AnyComponentWithIdentity], defaultId: AnyHashable?, @@ -565,7 +588,7 @@ public final class PagerComponent var contentBackgroundTransition = panelStateTransition diff --git a/submodules/Display/Source/UIKitUtils.swift b/submodules/Display/Source/UIKitUtils.swift index 3592dc0062..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()! diff --git a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift index 331c154d89..13ae1184ec 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDarkPresentationTheme.swift @@ -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..3ad0c85faa 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -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.6, 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/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index 59a51609cc..efb5fd4379 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -264,7 +264,7 @@ private final class AnimationCacheItemWriterInternal { } let width = roundUp(proposedWidth, multiple: 16) - let height = roundUp(proposedWidth, multiple: 16) + let height = roundUp(proposedHeight, multiple: 16) var isFirstFrame = false @@ -466,7 +466,7 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { } let width = roundUp(proposedWidth, multiple: 16) - let height = roundUp(proposedWidth, multiple: 16) + let height = roundUp(proposedHeight, multiple: 16) var isFirstFrame = false @@ -1336,7 +1336,7 @@ public final class AnimationCacheImpl: AnimationCache { self.queue = queue let fetchQueueCount: Int - if ProcessInfo.processInfo.activeProcessorCount > 2 { + if ProcessInfo.processInfo.processorCount > 2 { fetchQueueCount = 3 } else { fetchQueueCount = 2 diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 97ad8548ab..41b7ed28e1 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -599,11 +599,10 @@ private final class GroupHeaderLayer: UIView { color = theme.chat.inputPanel.primaryTextColor needsTintText = false } else { - //color = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1) - color = UIColor(white: 1.0, alpha: 0.0) + color = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor needsTintText = true } - let subtitleColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1) + let subtitleColor = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor let titleHorizontalOffset: CGFloat if isPremiumLocked { @@ -712,7 +711,12 @@ private final class GroupHeaderLayer: UIView { self.currentTextLayout = (title, color, textConstrainedWidth, textSize) } - let textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize) + let textFrame: CGRect + if (layoutType == .compact && hasClear) || subtitle != nil { + textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize) + } else { + textFrame = CGRect(origin: CGPoint(x: floor((constrainedSize.width - textSize.width) / 2.0), y: textOffsetY), size: textSize) + } self.textLayer.frame = textFrame self.tintTextLayer.frame = textFrame self.tintTextLayer.isHidden = !needsTintText @@ -808,7 +812,7 @@ private final class GroupHeaderLayer: UIView { } var clearSize = clearIconLayer.bounds.size - if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1)) { + if updateImage, let image = PresentationResourcesChat.chatInputMediaPanelGridDismissImage(theme, color: theme.chat.inputMediaPanel.panelContentVibrantOverlayColor) { clearSize = image.size clearIconLayer.contents = image.cgImage } @@ -816,12 +820,8 @@ private final class GroupHeaderLayer: UIView { tintClearIconLayer.contents = image.cgImage } - switch layoutType { - case .compact: - clearIconLayer.frame = CGRect(origin: CGPoint(x: titleHorizontalOffset + textSize.width + 4.0, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize) - case .detailed: - clearIconLayer.frame = CGRect(origin: CGPoint(x: constrainedSize.width - clearSize.width, y: floorToScreenPixels((textSize.height - clearSize.height) / 2.0)), size: clearSize) - } + 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 { @@ -836,10 +836,9 @@ private final class GroupHeaderLayer: UIView { } var size: CGSize - switch layoutType { - case .compact: + if layoutType == .compact && hasClear { size = CGSize(width: titleHorizontalOffset + textSize.width + clearWidth, height: constrainedSize.height) - case .detailed: + } else { size = CGSize(width: constrainedSize.width, height: constrainedSize.height) } @@ -885,7 +884,7 @@ private final class GroupHeaderLayer: UIView { self.separatorLayer = separatorLayer self.layer.addSublayer(separatorLayer) } - separatorLayer.backgroundColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withAlphaComponent(0.15).cgColor + 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 @@ -1190,7 +1189,7 @@ private final class GroupExpandActionButton: UIButton { let textConstrainedWidth: CGFloat = 100.0 let color = theme.list.itemCheckColors.foregroundColor - self.backgroundLayer.backgroundColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1).cgColor + self.backgroundLayer.backgroundColor = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor self.tintContainerLayer.backgroundColor = UIColor.white.cgColor let textSize: CGSize @@ -1254,6 +1253,7 @@ public final class EmojiPagerContentComponent: Component { 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 @@ -1267,6 +1267,7 @@ public final class EmojiPagerContentComponent: Component { 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, @@ -1279,6 +1280,7 @@ public final class EmojiPagerContentComponent: Component { self.performItemAction = performItemAction self.deleteBackwards = deleteBackwards self.openStickerSettings = openStickerSettings + self.openFeatured = openFeatured self.addGroupAction = addGroupAction self.clearGroup = clearGroup self.pushController = pushController @@ -1544,17 +1546,25 @@ public final class EmojiPagerContentComponent: Component { switch layoutType { case .compact: minItemsPerRow = 8 - self.nativeItemSize = 36.0 + self.nativeItemSize = 40.0 self.playbackItemSize = 48.0 self.verticalSpacing = 9.0 - minSpacing = 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) + self.headerInsets = 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) + self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 7.0, bottom: containerInsets.bottom, right: containerInsets.right + 7.0) + minSpacing = 9.0 + } + self.itemDefaultHeaderHeight = 24.0 self.itemFeaturedHeaderHeight = self.itemDefaultHeaderHeight - self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 12.0, bottom: containerInsets.bottom, right: containerInsets.right + 12.0) - self.headerInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 12.0, bottom: containerInsets.bottom, right: containerInsets.right + 12.0) case .detailed: minItemsPerRow = 5 - self.nativeItemSize = 71.0 + self.nativeItemSize = 70.0 self.playbackItemSize = 96.0 self.verticalSpacing = 2.0 minSpacing = 12.0 @@ -1571,9 +1581,13 @@ public final class EmojiPagerContentComponent: Component { self.itemsPerRow = max(minItemsPerRow, Int((itemHorizontalSpace + minSpacing) / (self.nativeItemSize + minSpacing))) - self.visibleItemSize = floor((itemHorizontalSpace - CGFloat(self.itemsPerRow - 1) * minSpacing) / CGFloat(self.itemsPerRow)) + self.visibleItemSize = self.nativeItemSize - self.horizontalSpacing = floor((itemHorizontalSpace - self.visibleItemSize * CGFloat(self.itemsPerRow)) / CGFloat(self.itemsPerRow - 1)) + 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 = [] @@ -1837,7 +1851,7 @@ public final class EmojiPagerContentComponent: Component { return } - if file.isVideoEmoji { + 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 { @@ -2139,7 +2153,7 @@ public final class EmojiPagerContentComponent: Component { override init(frame: CGRect) { self.backgroundView = BlurredBackgroundView(color: nil) - if ProcessInfo.processInfo.activeProcessorCount > 2 { + if ProcessInfo.processInfo.processorCount > 2 { self.shimmerHostView = PortalSourceView() self.standaloneShimmerEffect = StandaloneShimmerEffect() } else { @@ -2867,7 +2881,7 @@ public final class EmojiPagerContentComponent: Component { 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, 2.0) { + if distance2 > pow(max(itemLayer.bounds.width, itemLayer.bounds.height), 2.0) { continue } @@ -3060,10 +3074,7 @@ public final class EmojiPagerContentComponent: Component { actionButtonTitle = itemGroup.actionButtonTitle } - var hasTopSeparator = false - if case .detailed = itemLayout.layoutType, itemGroup.isFeatured, groupItems.groupIndex != 0 { - hasTopSeparator = true - } + let hasTopSeparator = false let groupHeaderSize = groupHeaderView.update( context: component.context, @@ -3108,7 +3119,7 @@ public final class EmojiPagerContentComponent: Component { self.scrollView.layer.insertSublayer(groupBorderLayer, at: 0) self.mirrorContentScrollView.layer.addSublayer(groupBorderLayer.tintContainerLayer) - groupBorderLayer.strokeColor = theme.chat.inputMediaPanel.stickersSectionTextColor.withMultipliedAlpha(0.1).cgColor + groupBorderLayer.strokeColor = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor groupBorderLayer.tintContainerLayer.strokeColor = UIColor.white.cgColor groupBorderLayer.lineWidth = 1.6 groupBorderLayer.lineCap = .round @@ -3293,9 +3304,9 @@ public final class EmojiPagerContentComponent: Component { } else { itemDimensions = CGSize(width: 512.0, height: 512.0) } - let itemNativeFitSize = itemDimensions.fitted(CGSize(width: itemLayout.nativeItemSize, height: itemLayout.nativeItemSize)) - let itemVisibleFitSize = itemDimensions.fitted(CGSize(width: itemLayout.visibleItemSize, height: itemLayout.visibleItemSize)) - let itemPlaybackSize = itemDimensions.fitted(CGSize(width: itemLayout.playbackItemSize, height: itemLayout.playbackItemSize)) + 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 @@ -3551,7 +3562,7 @@ public final class EmojiPagerContentComponent: Component { vibrancyEffectView.contentView.addSubview(self.mirrorContentScrollView) } - self.backgroundView.updateColor(color: theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75), enableBlur: true, forceKeepBlur: false, transition: transition.containedViewLayoutTransition) + 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) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 440c3a4787..23db4e67b5 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -74,7 +74,7 @@ public final class EntityKeyboardComponent: Component { } public let theme: PresentationTheme - public let bottomInset: CGFloat + public let containerInsets: UIEdgeInsets public let emojiContent: EmojiPagerContentComponent public let stickerContent: EmojiPagerContentComponent? public let gifContent: GifPagerContentComponent? @@ -93,7 +93,7 @@ public final class EntityKeyboardComponent: Component { public init( theme: PresentationTheme, - bottomInset: CGFloat, + containerInsets: UIEdgeInsets, emojiContent: EmojiPagerContentComponent, stickerContent: EmojiPagerContentComponent?, gifContent: GifPagerContentComponent?, @@ -111,7 +111,7 @@ public final class EntityKeyboardComponent: Component { isExpanded: Bool ) { self.theme = theme - self.bottomInset = bottomInset + self.containerInsets = containerInsets self.emojiContent = emojiContent self.stickerContent = stickerContent self.gifContent = gifContent @@ -133,7 +133,7 @@ public final class EntityKeyboardComponent: Component { if lhs.theme !== rhs.theme { return false } - if lhs.bottomInset != rhs.bottomInset { + if lhs.containerInsets != rhs.containerInsets { return false } if lhs.emojiContent != rhs.emojiContent { @@ -213,7 +213,7 @@ public final class EntityKeyboardComponent: Component { var contents: [AnyComponentWithIdentity<(EntityKeyboardChildEnvironment, PagerComponentChildEnvironment)>] = [] var contentTopPanels: [AnyComponentWithIdentity] = [] - var contentIcons: [AnyComponentWithIdentity] = [] + var contentIcons: [PagerComponentContentIcon] = [] var contentAccessoryLeftButtons: [AnyComponentWithIdentity] = [] var contentAccessoryRightButtons: [AnyComponentWithIdentity] = [] @@ -233,7 +233,7 @@ public final class EntityKeyboardComponent: Component { id: "recent", isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: "Chat/Input/Media/RecentTabIcon", + icon: .recent, theme: component.theme, title: "Recent", pressed: { [weak self] in @@ -246,7 +246,7 @@ public final class EntityKeyboardComponent: Component { id: "trending", isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: "Chat/Input/Media/TrendingGifs", + icon: .trending, theme: component.theme, title: "Trending", pressed: { [weak self] in @@ -290,11 +290,7 @@ public final class EntityKeyboardComponent: Component { reorderItems: { _ in } )))) - contentIcons.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/EntityInputGifsIcon", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: nil - )))) + 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", @@ -310,12 +306,26 @@ public final class EntityKeyboardComponent: Component { if let stickerContent = component.stickerContent { var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] + //TODO:localize + topStickerItems.append(EntityKeyboardTopPanelComponent.Item( + id: "featuredTop", + isReorderable: false, + content: AnyComponent(EntityKeyboardIconTopPanelComponent( + icon: .featured, + theme: component.theme, + title: "Featured", + 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: String] = [ - "saved": "Chat/Input/Media/SavedStickersTabIcon", - "recent": "Chat/Input/Media/RecentTabIcon", - "premium": "Peer Info/PremiumIcon" + let iconMapping: [String: EntityKeyboardIconTopPanelComponent.Icon] = [ + "saved": .saved, + "recent": .recent, + "premium": .premium ] //TODO:localize let titleMapping: [String: String] = [ @@ -323,12 +333,12 @@ public final class EntityKeyboardComponent: Component { "recent": "Recent", "premium": "Premium" ] - if let iconName = iconMapping[id], let title = titleMapping[id] { + if let icon = iconMapping[id], let title = titleMapping[id] { topStickerItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.supergroupId, isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: iconName, + icon: icon, theme: component.theme, title: title, pressed: { [weak self] in @@ -373,11 +383,7 @@ public final class EntityKeyboardComponent: Component { strongSelf.reorderPacks(category: .stickers, items: items) } )))) - contentIcons.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/EntityInputStickersIcon", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: nil - )))) + 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", @@ -407,19 +413,19 @@ public final class EntityKeyboardComponent: Component { if !itemGroup.items.isEmpty { if let id = itemGroup.groupId.base as? String { if id == "recent" { - let iconMapping: [String: String] = [ - "recent": "Chat/Input/Media/RecentTabIcon", + let iconMapping: [String: EntityKeyboardIconTopPanelComponent.Icon] = [ + "recent": .recent, ] //TODO:localize let titleMapping: [String: String] = [ "recent": "Recent", ] - if let iconName = iconMapping[id], let title = titleMapping[id] { + if let icon = iconMapping[id], let title = titleMapping[id] { topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.supergroupId, isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( - imageName: iconName, + icon: icon, theme: component.theme, title: title, pressed: { [weak self] in @@ -479,11 +485,7 @@ public final class EntityKeyboardComponent: Component { strongSelf.reorderPacks(category: .emoji, items: items) } )))) - contentIcons.append(AnyComponentWithIdentity(id: "emoji", component: AnyComponent(BundleIconComponent( - name: "Chat/Input/Media/EntityInputEmojiIcon", - tintColor: component.theme.chat.inputMediaPanel.panelIconColor, - maxSize: nil - )))) + 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", @@ -525,7 +527,7 @@ public final class EntityKeyboardComponent: Component { let pagerSize = self.pagerView.update( transition: transition, component: AnyComponent(PagerComponent( - contentInsets: UIEdgeInsets(top: 0.0, left: 0.0, bottom: 0.0, right: 0.0), + contentInsets: component.containerInsets, contents: contents, contentTopPanels: contentTopPanels, contentIcons: contentIcons, @@ -544,7 +546,7 @@ public final class EntityKeyboardComponent: Component { externalTopPanelContainer: component.externalTopPanelContainer, bottomPanel: AnyComponent(EntityKeyboardBottomPanelComponent( theme: component.theme, - bottomInset: component.bottomInset, + containerInsets: component.containerInsets, deleteBackwards: { [weak self] in self?.component?.emojiContent.inputInteractionHolder.inputInteraction?.deleteBackwards() AudioServicesPlaySystemSound(0x451) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift index a1925f41d8..5cc31d874b 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardBottomPanelComponent.swift @@ -10,19 +10,31 @@ import ComponentDisplayAdapters import BundleIconComponent private final class BottomPanelIconComponent: Component { - let content: AnyComponent + let imageName: String + let isHighlighted: Bool + let theme: PresentationTheme let action: () -> Void init( - content: AnyComponent, + imageName: String, + isHighlighted: Bool, + theme: PresentationTheme, action: @escaping () -> Void ) { - self.content = content + self.imageName = imageName + self.isHighlighted = isHighlighted + self.theme = theme self.action = action } static func ==(lhs: BottomPanelIconComponent, rhs: BottomPanelIconComponent) -> Bool { - if lhs.content != rhs.content { + if lhs.imageName != rhs.imageName { + return false + } + if lhs.isHighlighted != rhs.isHighlighted { + return false + } + if lhs.theme !== rhs.theme { return false } @@ -30,12 +42,12 @@ private final class BottomPanelIconComponent: Component { } final class View: UIView { - let contentView: ComponentHostView + let contentView: UIImageView var component: BottomPanelIconComponent? override init(frame: CGRect) { - self.contentView = ComponentHostView() + self.contentView = UIImageView() self.contentView.isUserInteractionEnabled = false super.init(frame: frame) @@ -55,16 +67,27 @@ private final class BottomPanelIconComponent: Component { } 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: 32.0, height: 32.0) + let size = CGSize(width: 28.0, height: 28.0) - let contentSize = self.contentView.update( - transition: transition, - component: component.content, - environment: {}, - containerSize: size - ) + 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 @@ -84,16 +107,16 @@ final class EntityKeyboardBottomPanelComponent: Component { typealias EnvironmentType = PagerComponentPanelEnvironment let theme: PresentationTheme - let bottomInset: CGFloat + let containerInsets: UIEdgeInsets let deleteBackwards: () -> Void init( theme: PresentationTheme, - bottomInset: CGFloat, + containerInsets: UIEdgeInsets, deleteBackwards: @escaping () -> Void ) { self.theme = theme - self.bottomInset = bottomInset + self.containerInsets = containerInsets self.deleteBackwards = deleteBackwards } @@ -101,7 +124,7 @@ final class EntityKeyboardBottomPanelComponent: Component { if lhs.theme !== rhs.theme { return false } - if lhs.bottomInset != rhs.bottomInset { + if lhs.containerInsets != rhs.containerInsets { return false } @@ -160,8 +183,8 @@ final class EntityKeyboardBottomPanelComponent: Component { self.highlightedIconBackgroundView.backgroundColor = component.theme.chat.inputMediaPanel.panelHighlightedIconBackgroundColor } - let intrinsicHeight: CGFloat = 38.0 - let height = intrinsicHeight + component.bottomInset + let intrinsicHeight: CGFloat = 34.0 + let height = intrinsicHeight + component.containerInsets.bottom let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value let activeContentId = panelEnvironment.activeContentId @@ -194,7 +217,7 @@ final class EntityKeyboardBottomPanelComponent: Component { environment: {}, containerSize: CGSize(width: .greatestFiniteMagnitude, height: intrinsicHeight) ) - leftAccessoryButtonTransition.setFrame(view: leftAccessoryButton.view, frame: CGRect(origin: CGPoint(x: 2.0, y: 2.0), size: leftAccessoryButtonSize)) + leftAccessoryButtonTransition.setFrame(view: leftAccessoryButton.view, frame: CGRect(origin: CGPoint(x: component.containerInsets.left + 2.0, y: 2.0), size: leftAccessoryButtonSize)) } else { self.leftAccessoryButton = nil } @@ -246,7 +269,7 @@ final class EntityKeyboardBottomPanelComponent: Component { environment: {}, containerSize: CGSize(width: .greatestFiniteMagnitude, height: intrinsicHeight) ) - rightAccessoryButtonTransition.setFrame(view: rightAccessoryButton.view, frame: CGRect(origin: CGPoint(x: availableSize.width - 2.0 - rightAccessoryButtonSize.width, y: 2.0), size: rightAccessoryButtonSize)) + 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 } @@ -296,13 +319,15 @@ final class EntityKeyboardBottomPanelComponent: Component { let iconSize = iconView.update( transition: iconTransition, component: AnyComponent(BottomPanelIconComponent( - content: icon.component, + imageName: icon.imageName, + isHighlighted: icon.id == activeContentId, + theme: component.theme, action: { navigateToContentId(icon.id) } )), environment: {}, - containerSize: CGSize(width: 32.0, height: 32.0) + containerSize: CGSize(width: 28.0, height: 28.0) ) iconInfos[icon.id] = (size: iconSize, transition: iconTransition) @@ -316,8 +341,8 @@ final class EntityKeyboardBottomPanelComponent: Component { } var nextIconOrigin = CGPoint(x: floor((availableSize.width - iconTotalSize.width) / 2.0), y: floor((intrinsicHeight - iconTotalSize.height) / 2.0)) - if component.bottomInset > 0.0 { - nextIconOrigin.y += 2.0 + if component.containerInsets.bottom > 0.0 { + nextIconOrigin.y += 3.0 } if panelEnvironment.contentIcons.count > 1 { @@ -332,6 +357,14 @@ final class EntityKeyboardBottomPanelComponent: Component { 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 diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift index 7057727731..3f7b663927 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopContainerPanelComponent.swift @@ -88,7 +88,7 @@ final class EntityKeyboardTopContainerPanelComponent: Component { } func update(component: EntityKeyboardTopContainerPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { - let intrinsicHeight: CGFloat = 41.0 + let intrinsicHeight: CGFloat = 34.0 let height = intrinsicHeight let panelEnvironment = environment[PagerComponentPanelEnvironment.self].value diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 5d6506e888..868da96462 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -104,6 +104,9 @@ final class EntityKeyboardAnimationTopPanelComponent: 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( @@ -119,7 +122,7 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { renderer: component.animationRenderer, placeholderColor: .lightGray, blurredBadgeColor: .clear, - pointSize: CGSize(width: 44.0, height: 44.0), + pointSize: displaySize, onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in guard let strongSelf = self else { return @@ -135,8 +138,9 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { } } - let iconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 28.0, height: 28.0) - let iconFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize.width) / 2.0), y: 0.0), size: iconSize) + let iconFitSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 26.0, height: 26.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) if let itemLayer = self.itemLayer { transition.setPosition(layer: itemLayer, position: CGPoint(x: iconFrame.midX, y: iconFrame.midY)) @@ -234,25 +238,33 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { final class EntityKeyboardIconTopPanelComponent: Component { typealias EnvironmentType = EntityKeyboardTopPanelItemEnvironment - let imageName: String + 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( - imageName: String, + icon: Icon, theme: PresentationTheme, title: String, pressed: @escaping () -> Void ) { - self.imageName = imageName + self.icon = icon self.theme = theme self.title = title self.pressed = pressed } static func ==(lhs: EntityKeyboardIconTopPanelComponent, rhs: EntityKeyboardIconTopPanelComponent) -> Bool { - if lhs.imageName != rhs.imageName { + if lhs.icon != rhs.icon { return false } if lhs.theme !== rhs.theme { @@ -293,11 +305,19 @@ final class EntityKeyboardIconTopPanelComponent: Component { func update(component: EntityKeyboardIconTopPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value - if self.component?.imageName != component.imageName { - self.iconView.image = generateTintedImage(image: UIImage(bundleImageName: component.imageName), color: component.theme.chat.inputMediaPanel.panelIconColor) - - if component.imageName.hasSuffix("PremiumIcon") { - self.iconView.image = generateImage(CGSize(width: 44.0, height: 42.0), contextGenerator: { size, context in + 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: 42.0), contextGenerator: { size, context in context.clear(CGRect(origin: CGPoint(), size: size)) if let image = UIImage(bundleImageName: "Peer Info/PremiumIcon") { if let cgImage = image.cgImage { @@ -318,12 +338,26 @@ final class EntityKeyboardIconTopPanelComponent: Component { } }) } + + self.iconView.image = image } self.component = component - let nativeIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 28.0, height: 28.0) - let boundingIconSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 38.0, height: 38.0) : CGSize(width: 28.0, height: 28.0) + 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) @@ -406,6 +440,36 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { } 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 : 24.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] = [:] @@ -415,6 +479,8 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { private var component: EntityKeyboardStaticStickersPanelComponent? private var itemEnvironment: EntityKeyboardTopPanelItemEnvironment? + private var itemLayout: ItemLayout? + private var ignoreScrolling: Bool = false override init(frame: CGRect) { @@ -452,13 +518,27 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { @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, view.frame.insetBy(dx: -4.0, dy: -4.0).contains(scrollViewLocation) { - self.component?.pressed(id) - break + 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) + } } } @@ -470,25 +550,17 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { } private func updateVisibleItems(transition: Transition, animateAppearingItems: Bool) { - guard let component = self.component, let itemEnvironment = self.itemEnvironment else { + guard let component = self.component, let itemEnvironment = self.itemEnvironment, let itemLayout = self.itemLayout else { return } var validItemIds = Set() let visibleBounds = self.scrollView.bounds - let componentHeight: CGFloat = self.scrollView.contentSize.height - - let isExpanded = componentHeight > 32.0 - let items = EmojiPagerContentComponent.StaticEmojiSegment.allCases - let itemSize: CGFloat = isExpanded ? 42.0 : 32.0 - let itemSpacing: CGFloat = 4.0 - let sideInset: CGFloat = isExpanded ? 5.0 : 2.0 - let itemOffset: CGFloat = isExpanded ? -8.0 : 0.0 for i in 0 ..< items.count { - let itemFrame = CGRect(origin: CGPoint(x: sideInset + CGFloat(i) * (itemSize + itemSpacing), y: floor(componentHeight - itemSize) / 2.0 + itemOffset), size: CGSize(width: itemSize, height: itemSize)) - if visibleBounds.intersects(itemFrame) { + let itemFrame = itemLayout.frame(at: i) + if true/*visibleBounds.intersects(itemFrame)*/ { let item = items[i] validItemIds.insert(item) @@ -503,6 +575,7 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { itemView = ComponentView() self.visibleItemViews[item] = itemView } + let _ = animateItem let animationName: String switch item { @@ -526,29 +599,45 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { let color: UIColor if itemEnvironment.highlightedSubgroupId == AnyHashable(items[i].rawValue) { - color = component.theme.chat.inputMediaPanel.panelIconColor.mixedWith(component.theme.chat.inputPanel.primaryTextColor, alpha: 0.35) + color = component.theme.chat.inputMediaPanel.panelHighlightedIconColor } else { color = component.theme.chat.inputMediaPanel.panelIconColor } + let _ = itemTransition let _ = itemView.update( - transition: itemTransition, + transition: .immediate, component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( name: animationName, - mode: animateItem ? .animating(loop: false) : .still(position: .end) + mode: .still(position: .end) ), colors: ["__allcolors__": color], - size: CGSize(width: itemSize, height: itemSize) + size: CGSize(width: itemLayout.baseItemSize, height: itemLayout.baseItemSize) )), environment: {}, - containerSize: CGSize(width: itemSize, height: itemSize) + containerSize: CGSize(width: itemLayout.baseItemSize, height: itemLayout.baseItemSize) ) if let view = itemView.view { if view.superview == nil { self.scrollView.addSubview(view) } - itemTransition.setFrame(view: view, frame: itemFrame) + + 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() + } + } + } } } } @@ -566,9 +655,6 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { } func update(component: EntityKeyboardStaticStickersPanelComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { - transition.setFrame(view: self.scrollViewContainer, frame: CGRect(origin: CGPoint(), size: availableSize)) - transition.setCornerRadius(layer: self.scrollViewContainer.layer, cornerRadius: min(availableSize.width / 2.0, availableSize.height / 2.0)) - let itemEnvironment = environment[EntityKeyboardTopPanelItemEnvironment.self].value var scrollToItem: AnyHashable? @@ -579,30 +665,32 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { self.component = component self.itemEnvironment = itemEnvironment - let isExpanded = itemEnvironment.isExpanded - let itemSize: CGFloat = isExpanded ? 42.0 : 32.0 - let itemSpacing: CGFloat = 4.0 - let sideInset: CGFloat = isExpanded ? 5.0 : 2.0 - let itemCount = EmojiPagerContentComponent.StaticEmojiSegment.allCases.count + 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, 160.0), height: availableSize.height)) - self.scrollView.contentSize = CGSize(width: sideInset * 2.0 + itemSize * CGFloat(itemCount) + itemSpacing * CGFloat(itemCount - 1), height: availableSize.height) + self.scrollView.frame = CGRect(origin: CGPoint(), size: CGSize(width: max(availableSize.width, 126.0), height: availableSize.height)) + self.scrollView.contentSize = itemLayout.contentSize self.ignoreScrolling = false self.updateVisibleItems(transition: transition, animateAppearingItems: false) - if (!itemEnvironment.isHighlighted || isExpanded) && self.scrollView.contentOffset.x != 0.0 { + 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 = CGRect(origin: CGPoint(x: sideInset + CGFloat(i) * (itemSize + itemSpacing), y: 0.0), size: CGSize(width: itemSize, height: itemSize)) - self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -sideInset, dy: 0.0), animated: true) + let itemFrame = itemLayout.frame(at: i) + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -itemLayout.sideInset, dy: 0.0), animated: true) break } } @@ -954,28 +1042,30 @@ final class EntityKeyboardTopPanelComponent: Component { var innerFrame: CGRect } + let topInset: CGFloat = -3.0 let sideInset: CGFloat = 7.0 let itemSize: CGSize let staticItemSize: CGSize let staticExpandedItemSize: CGSize let innerItemSize: CGSize - let itemSpacing: CGFloat = 15.0 + let itemSpacing: CGFloat let contentSize: CGSize let isExpanded: Bool let items: [Item] init(isExpanded: Bool, height: CGFloat, items: [ItemDescription]) { self.isExpanded = isExpanded - self.itemSize = self.isExpanded ? CGSize(width: 54.0, height: 68.0) : CGSize(width: 32.0, height: 32.0) + 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: 160.0, height: 32.0) - self.innerItemSize = self.isExpanded ? CGSize(width: 50.0, height: 62.0) : CGSize(width: 28.0, height: 28.0) + self.staticExpandedItemSize = self.isExpanded ? self.staticItemSize : CGSize(width: 126.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 = floor((contentSize.height - self.itemSize.height) / 2.0) + let itemY = self.topInset + floor((contentSize.height - self.itemSize.height) / 2.0) for item in items { if isFirst { isFirst = false @@ -1446,8 +1536,8 @@ final class EntityKeyboardTopPanelComponent: Component { } var visibleBounds = self.scrollView.bounds - visibleBounds.origin.x -= 200.0 - visibleBounds.size.width += 400.0 + visibleBounds.origin.x -= 280.0 + visibleBounds.size.width += 560.0 let scale = max(0.01, self.visibilityFraction) @@ -1511,7 +1601,7 @@ final class EntityKeyboardTopPanelComponent: Component { let panelEnvironment = environment[EntityKeyboardTopContainerPanelEnvironment.self].value self.environment = panelEnvironment - let isExpanded = availableSize.height > 41.0 + let isExpanded = availableSize.height > 34.0 let wasExpanded = self.isExpanded self.isExpanded = isExpanded @@ -1576,8 +1666,8 @@ final class EntityKeyboardTopPanelComponent: Component { } var visibleBounds = self.scrollView.bounds - visibleBounds.origin.x -= 200.0 - visibleBounds.size.width += 400.0 + visibleBounds.origin.x -= 280.0 + visibleBounds.size.width += 560.0 let previousVisibleRange = previousItemLayout.visibleItemRange(for: visibleBounds) if previousVisibleRange.minIndex <= previousVisibleRange.maxIndex { @@ -1626,8 +1716,8 @@ final class EntityKeyboardTopPanelComponent: Component { updatedBounds = newBounds var updatedVisibleBounds = newBounds - updatedVisibleBounds.origin.x -= 200.0 - updatedVisibleBounds.size.width += 400.0 + updatedVisibleBounds.origin.x -= 280.0 + updatedVisibleBounds.size.width += 560.0 let updatedVisibleRange = itemLayout.visibleItemRange(for: updatedVisibleBounds) if useRightAnchor { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index 7f8c132158..8171d8976e 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -755,7 +755,7 @@ public final class GifPagerContentComponent: Component { guard let theme = self.theme else { return } - self.backgroundView.updateColor(color: theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75), enableBlur: true, forceKeepBlur: false, transition: transition.containedViewLayoutTransition) + 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) } diff --git a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift index bc09070b5b..7856c916f0 100644 --- a/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift +++ b/submodules/TelegramUI/Components/LottieAnimationCache/Sources/LottieAnimationCache.swift @@ -17,7 +17,7 @@ public func cacheLottieAnimation(data: Data, width: Int, height: Int, writer: An let frameSkip: Int if animation.frameRate >= 60 { - if ProcessInfo.processInfo.activeProcessorCount > 2 { + if ProcessInfo.processInfo.processorCount > 2 { frameSkip = 1 } else { frameSkip = 2 diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift index df715c5a18..00f1837d90 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationMetalRenderer.swift @@ -779,7 +779,7 @@ public final class MultiAnimationMetalRendererImpl: MultiAnimationRenderer { } public init() { - if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.activeProcessorCount > 2 { + if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.processorCount > 2 { self.frameSkip = 1 } else { self.frameSkip = 2 diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index b76800a424..126894163b 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -131,7 +131,9 @@ private final class ItemAnimationContext { 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( @@ -148,7 +150,6 @@ private final class ItemAnimationContext { intent: .defaultIntent ) if let image = image { - let size = CGSize(width: CGFloat(blurredWidth), height: CGFloat(blurredHeight)) context.withFlippedContext { c in c.setFillColor((color ?? .white).cgColor) c.fill(CGRect(origin: CGPoint(), size: size)) @@ -202,6 +203,11 @@ private final class ItemAnimationContext { } 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() @@ -556,7 +562,7 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { } public init() { - if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.activeProcessorCount > 2 { + if !ProcessInfo.processInfo.isLowPowerModeEnabled && ProcessInfo.processInfo.processorCount > 2 { self.frameSkip = 1 } else { self.frameSkip = 2 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 index f93f8f8fb7..d4b2093823 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "filename" : "ic_clear.pdf", + "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/EntityInputClearIcon.imageset/ic_clear.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/ic_clear.pdf deleted file mode 100644 index 559ad92734..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputClearIcon.imageset/ic_clear.pdf +++ /dev/null @@ -1,107 +0,0 @@ -%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 3.180420 6.169983 cm -0.000000 0.000000 0.000000 scn -7.131522 16.439991 m -8.015658 17.225891 9.157463 17.660004 10.340398 17.660004 c -19.819601 17.660004 l -22.487137 17.660004 24.649601 15.497540 24.649601 12.830004 c -24.649601 4.830004 l -24.649601 2.162468 22.487137 0.000004 19.819601 0.000004 c -10.340399 0.000004 l -9.157463 0.000004 8.015657 0.434116 7.131521 1.220016 c -0.949850 6.714835 l --0.316617 7.840584 -0.316617 9.819424 0.949850 10.945172 c -7.131522 16.439991 l -h -10.340398 16.000004 m -9.564020 16.000004 8.814637 15.715089 8.234365 15.199291 c -2.052694 9.704473 l -1.529102 9.239058 1.529102 8.420950 2.052694 7.955535 c -8.234365 2.460716 l -8.814637 1.944919 9.564020 1.660004 10.340399 1.660004 c -19.819601 1.660004 l -21.570343 1.660004 22.989601 3.079261 22.989601 4.830004 c -22.989601 12.830004 l -22.989601 14.580747 21.570343 16.000004 19.819601 16.000004 c -10.340398 16.000004 l -h -10.732702 12.916903 m -11.056838 13.241037 11.582364 13.241037 11.906500 12.916903 c -14.819601 10.003801 l -17.732702 12.916903 l -18.056837 13.241037 18.582365 13.241037 18.906500 12.916903 c -19.230635 12.592768 19.230635 12.067240 18.906500 11.743105 c -15.993399 8.830004 l -18.906500 5.916903 l -19.230635 5.592768 19.230635 5.067240 18.906500 4.743105 c -18.582365 4.418970 18.056837 4.418970 17.732702 4.743105 c -14.819601 7.656206 l -11.906500 4.743105 l -11.582364 4.418970 11.056838 4.418970 10.732702 4.743105 c -10.408567 5.067241 10.408567 5.592767 10.732702 5.916903 c -13.645803 8.830004 l -10.732702 11.743105 l -10.408567 12.067240 10.408567 12.592768 10.732702 12.916903 c -h -f* -n -Q - -endstream -endobj - -3 0 obj - 1651 -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 -0000001741 00000 n -0000001764 00000 n -0000001937 00000 n -0000002011 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -2070 -%%EOF \ No newline at end of file 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 index 8d1829694d..bf55af4ccb 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "filename" : "ic_emoji.pdf", + "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/EntityInputEmojiIcon.imageset/ic_emoji.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/ic_emoji.pdf deleted file mode 100644 index 51dd673605..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputEmojiIcon.imageset/ic_emoji.pdf +++ /dev/null @@ -1,123 +0,0 @@ -%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 7.292999 5.741058 cm -0.000000 0.000000 0.000000 scn -7.706251 7.052563 m -9.859218 7.052563 11.806032 7.518116 13.204300 7.852490 c -14.570075 8.179095 15.412500 8.380550 15.412500 7.900764 c -15.412500 3.644719 11.962295 0.194514 7.706251 0.194514 c -3.450206 0.194514 0.000000 3.644719 0.000000 7.900764 c -0.000000 8.380550 0.842425 8.179095 2.208200 7.852490 c -3.606467 7.518116 5.553283 7.052563 7.706251 7.052563 c -h -12.468611 6.348519 m -11.392131 6.066849 9.742197 5.635127 7.697002 5.635127 c -5.651808 5.635127 4.001874 6.066849 2.925394 6.348519 c -2.030582 6.582655 1.532002 6.713113 1.532002 6.405752 c -1.532002 3.455799 6.013958 3.323253 7.697002 3.323253 c -9.586575 3.323253 13.862001 3.456314 13.862001 6.405752 c -13.862001 6.713113 13.363423 6.582655 12.468611 6.348519 c -h -f* -n -Q -q -1.000000 0.000000 -0.000000 1.000000 2.669983 2.669983 cm -0.000000 0.000000 0.000000 scn -12.330000 23.000004 m -6.437122 23.000004 1.660000 18.222881 1.660000 12.330004 c -1.660000 6.437126 6.437122 1.660004 12.330000 1.660004 c -18.222878 1.660004 23.000000 6.437126 23.000000 12.330004 c -23.000000 18.222881 18.222878 23.000004 12.330000 23.000004 c -h -0.000000 12.330004 m -0.000000 19.139675 5.520329 24.660004 12.330000 24.660004 c -19.139671 24.660004 24.660000 19.139675 24.660000 12.330004 c -24.660000 5.520332 19.139671 0.000004 12.330000 0.000004 c -5.520329 0.000004 0.000000 5.520332 0.000000 12.330004 c -h -f* -n -Q -q -1.000000 0.000000 -0.000000 1.000000 10.000000 16.250000 cm -0.000000 0.000000 0.000000 scn -3.000000 1.750000 m -3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c -0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c -0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c -2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 17.000000 16.250000 cm -0.000000 0.000000 0.000000 scn -3.000000 1.750000 m -3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c -0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c -0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c -2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c -h -f -n -Q - -endstream -endobj - -3 0 obj - 2167 -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 -0000002257 00000 n -0000002280 00000 n -0000002453 00000 n -0000002527 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -2586 -%%EOF \ No newline at end of file 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 index 35222f8570..1e503c705b 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "filename" : "ic_gifs.pdf", + "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/EntityInputGifsIcon.imageset/ic_gifs.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/ic_gifs.pdf deleted file mode 100644 index 410ff918fa..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGifsIcon.imageset/ic_gifs.pdf +++ /dev/null @@ -1,128 +0,0 @@ -%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.669983 2.670013 cm -0.000000 0.000000 0.000000 scn -12.330000 22.999989 m -6.437122 22.999989 1.660000 18.222866 1.660000 12.329988 c -1.660000 6.437111 6.437122 1.659988 12.330000 1.659988 c -18.222878 1.659988 23.000000 6.437111 23.000000 12.329988 c -23.000000 18.222866 18.222878 22.999989 12.330000 22.999989 c -h -0.000000 12.329988 m -0.000000 19.139660 5.520329 24.659988 12.330000 24.659988 c -19.139671 24.659988 24.660000 19.139660 24.660000 12.329988 c -24.660000 5.520317 19.139671 -0.000011 12.330000 -0.000011 c -5.520329 -0.000011 0.000000 5.520317 0.000000 12.329988 c -h -17.108725 15.659992 m -17.129999 15.659988 l -18.830000 15.659988 l -19.288397 15.659988 19.660000 15.288384 19.660000 14.829988 c -19.660000 14.371593 19.288397 13.999989 18.830000 13.999989 c -17.160000 13.999989 l -17.160000 13.159988 l -18.830000 13.159988 l -19.288397 13.159988 19.660000 12.788384 19.660000 12.329988 c -19.660000 11.871593 19.288397 11.499989 18.830000 11.499989 c -17.160000 11.499989 l -17.160000 9.829988 l -17.160000 9.371592 16.788397 8.999989 16.330000 8.999989 c -15.871604 8.999989 15.500000 9.371592 15.500000 9.829988 c -15.500000 12.329988 l -15.500000 14.029988 l -15.499996 14.051264 l -15.499962 14.172362 15.499924 14.307926 15.509568 14.425976 c -15.520575 14.560680 15.548159 14.743810 15.644961 14.933796 c -15.772472 15.184052 15.975937 15.387516 16.226192 15.515027 c -16.416180 15.611830 16.599308 15.639414 16.734013 15.650420 c -16.852062 15.660065 16.987627 15.660027 17.108725 15.659992 c -h -13.330000 15.659988 m -13.788396 15.659988 14.160000 15.288384 14.160000 14.829988 c -14.160000 9.829988 l -14.160000 9.371592 13.788396 8.999989 13.330000 8.999989 c -12.871604 8.999989 12.500000 9.371592 12.500000 9.829988 c -12.500000 14.829988 l -12.500000 15.288384 12.871604 15.659988 13.330000 15.659988 c -h -8.330000 15.659988 m -6.490891 15.659988 5.000000 14.169097 5.000000 12.329988 c -5.000000 10.490880 6.490891 8.999989 8.330000 8.999989 c -9.670162 8.999989 11.076591 9.880583 11.385777 11.507551 c -11.393431 11.547824 l -11.397078 11.588655 l -11.427523 11.929440 l -11.486586 12.590580 10.965777 13.159988 10.302004 13.159988 c -9.330000 13.159988 l -8.871603 13.159988 8.500000 12.788385 8.500000 12.329988 c -8.500000 11.871592 8.871603 11.499989 9.330000 11.499989 c -9.657213 11.499989 l -9.421404 10.962639 8.887941 10.659988 8.330000 10.659988 c -7.407684 10.659988 6.660000 11.407673 6.660000 12.329988 c -6.660000 13.252304 7.407684 13.999989 8.330000 13.999989 c -8.609308 13.999989 8.870320 13.932076 9.099771 13.812578 c -9.506336 13.600842 10.007568 13.758780 10.219306 14.165344 c -10.431044 14.571908 10.273106 15.073140 9.866541 15.284878 c -9.405935 15.524760 8.882543 15.659988 8.330000 15.659988 c -h -f* -n -Q - -endstream -endobj - -3 0 obj - 2783 -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 -0000002873 00000 n -0000002896 00000 n -0000003069 00000 n -0000003143 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -3202 -%%EOF \ No newline at end of file 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 index 28fd472ac9..a4c1cddbca 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "filename" : "planet.pdf", + "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/EntityInputGlobeIcon.imageset/planet.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/planet.pdf deleted file mode 100644 index c2225439d8..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputGlobeIcon.imageset/planet.pdf +++ /dev/null @@ -1,255 +0,0 @@ -%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 3.500000 1.839844 cm -0.000000 0.000000 0.000000 scn -22.170000 13.160156 m -22.170000 7.267279 17.392878 2.490156 11.500000 2.490156 c -11.500000 0.830156 l -18.309671 0.830156 23.830000 6.350485 23.830000 13.160156 c -22.170000 13.160156 l -h -11.500000 2.490156 m -5.607122 2.490156 0.830000 7.267279 0.830000 13.160156 c --0.830000 13.160156 l --0.830000 6.350485 4.690329 0.830156 11.500000 0.830156 c -11.500000 2.490156 l -h -0.830000 13.160156 m -0.830000 19.053034 5.607122 23.830156 11.500000 23.830156 c -11.500000 25.490156 l -4.690329 25.490156 -0.830000 19.969828 -0.830000 13.160156 c -0.830000 13.160156 l -h -11.500000 23.830156 m -17.392878 23.830156 22.170000 19.053034 22.170000 13.160156 c -23.830000 13.160156 l -23.830000 19.969828 18.309671 25.490156 11.500000 25.490156 c -11.500000 23.830156 l -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 8.500000 1.839844 cm -0.000000 0.000000 0.000000 scn -12.170000 13.160156 m -12.170000 10.100716 11.467313 7.371819 10.373627 5.436836 c -9.265684 3.476629 7.863927 2.490156 6.500000 2.490156 c -6.500000 0.830156 l -8.725924 0.830156 10.574167 2.418047 11.818761 4.620020 c -13.077613 6.847219 13.830000 9.868322 13.830000 13.160156 c -12.170000 13.160156 l -h -6.500000 2.490156 m -5.136073 2.490156 3.734316 3.476629 2.626373 5.436836 c -1.532687 7.371819 0.830000 10.100716 0.830000 13.160156 c --0.830000 13.160156 l --0.830000 9.868322 -0.077613 6.847219 1.181239 4.620020 c -2.425833 2.418047 4.274076 0.830156 6.500000 0.830156 c -6.500000 2.490156 l -h -0.830000 13.160156 m -0.830000 16.219597 1.532687 18.948494 2.626373 20.883476 c -3.734316 22.843683 5.136073 23.830156 6.500000 23.830156 c -6.500000 25.490156 l -4.274076 25.490156 2.425833 23.902266 1.181239 21.700291 c --0.077613 19.473093 -0.830000 16.451990 -0.830000 13.160156 c -0.830000 13.160156 l -h -6.500000 23.830156 m -7.863927 23.830156 9.265684 22.843683 10.373627 20.883476 c -11.467313 18.948494 12.170000 16.219597 12.170000 13.160156 c -13.830000 13.160156 l -13.830000 16.451990 13.077613 19.473093 11.818761 21.700291 c -10.574167 23.902266 8.725924 25.490156 6.500000 25.490156 c -6.500000 23.830156 l -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 15.000000 3.500000 cm -0.000000 0.000000 0.000000 scn --0.830000 23.000000 m --0.830000 0.000000 l -0.830000 0.000000 l -0.830000 23.000000 l --0.830000 23.000000 l -h -f -n -Q -q -0.000000 1.000000 -1.000000 0.000000 5.160156 15.000000 cm -0.000000 0.000000 0.000000 scn --0.830000 1.660156 m --0.830000 -21.339844 l -0.830000 -21.339844 l -0.830000 1.660156 l --0.830000 1.660156 l -h -f -n -Q -q -0.000000 1.000000 -1.000000 0.000000 9.019043 8.000000 cm -0.000000 0.000000 0.000000 scn -0.000000 3.519043 m --0.686377 3.052367 -0.686606 3.052704 -0.686827 3.053029 c --0.686890 3.053123 -0.687103 3.053437 -0.687230 3.053624 c --0.687484 3.053999 -0.687707 3.054330 -0.687901 3.054617 c --0.688287 3.055190 -0.688552 3.055586 -0.688699 3.055805 c --0.688991 3.056243 -0.688808 3.055973 -0.688163 3.054991 c --0.686874 3.053027 -0.683741 3.048217 -0.678884 3.040542 c --0.669169 3.025192 -0.652556 2.998377 -0.630008 2.959931 c --0.584915 2.883047 -0.516061 2.759615 -0.431147 2.588317 c --0.261366 2.245815 -0.027114 1.711416 0.209833 0.974417 c -0.683340 -0.498374 1.170000 -2.787649 1.170000 -5.980957 c -2.830000 -5.980957 l -2.830000 -2.615824 2.316660 -0.155099 1.790166 1.482499 c -1.527114 2.300695 1.261366 2.911589 1.056147 3.325581 c -0.953561 3.532529 0.866165 3.690144 0.801883 3.799746 c -0.769744 3.854543 0.743388 3.897330 0.723805 3.928271 c -0.714015 3.943742 0.705917 3.956251 0.699638 3.965818 c -0.696498 3.970602 0.693813 3.974651 0.691598 3.977967 c -0.690490 3.979625 0.689500 3.981099 0.688629 3.982391 c -0.688194 3.983037 0.687788 3.983638 0.687413 3.984192 c -0.687225 3.984469 0.686966 3.984851 0.686872 3.984990 c -0.686621 3.985360 0.686377 3.985719 0.000000 3.519043 c -h -1.170000 -5.980957 m -1.170000 -9.174265 0.683340 -11.463540 0.209833 -12.936331 c --0.027114 -13.673330 -0.261366 -14.207729 -0.431147 -14.550232 c --0.516061 -14.721529 -0.584915 -14.844961 -0.630008 -14.921844 c --0.652556 -14.960291 -0.669169 -14.987106 -0.678884 -15.002457 c --0.683741 -15.010132 -0.686874 -15.014940 -0.688163 -15.016905 c --0.688808 -15.017887 -0.688991 -15.018158 -0.688699 -15.017719 c --0.688552 -15.017500 -0.688287 -15.017103 -0.687901 -15.016531 c --0.687707 -15.016245 -0.687484 -15.015913 -0.687230 -15.015539 c --0.687103 -15.015350 -0.686890 -15.015036 -0.686827 -15.014942 c --0.686606 -15.014618 -0.686377 -15.014280 0.000000 -15.480957 c -0.686377 -15.947634 0.686621 -15.947273 0.686872 -15.946903 c -0.686966 -15.946766 0.687225 -15.946383 0.687413 -15.946106 c -0.687788 -15.945551 0.688194 -15.944952 0.688629 -15.944305 c -0.689500 -15.943014 0.690490 -15.941538 0.691598 -15.939880 c -0.693813 -15.936565 0.696498 -15.932516 0.699638 -15.927732 c -0.705917 -15.918165 0.714015 -15.905657 0.723805 -15.890184 c -0.743388 -15.859243 0.769744 -15.816458 0.801883 -15.761660 c -0.866165 -15.652058 0.953561 -15.494444 1.056147 -15.287495 c -1.261366 -14.873503 1.527114 -14.262609 1.790166 -13.444414 c -2.316660 -11.806815 2.830000 -9.346090 2.830000 -5.980957 c -1.170000 -5.980957 l -h -f -n -Q -q -0.000000 -1.000000 1.000000 0.000000 20.980957 22.000000 cm -0.000000 0.000000 0.000000 scn -0.000000 3.519043 m --0.686377 3.052367 -0.686606 3.052704 -0.686827 3.053029 c --0.686890 3.053123 -0.687103 3.053437 -0.687230 3.053624 c --0.687484 3.053999 -0.687707 3.054330 -0.687901 3.054617 c --0.688287 3.055190 -0.688552 3.055586 -0.688699 3.055805 c --0.688991 3.056243 -0.688808 3.055973 -0.688163 3.054991 c --0.686874 3.053027 -0.683741 3.048217 -0.678884 3.040542 c --0.669169 3.025192 -0.652556 2.998377 -0.630008 2.959931 c --0.584915 2.883047 -0.516061 2.759615 -0.431147 2.588317 c --0.261366 2.245815 -0.027114 1.711416 0.209833 0.974417 c -0.683340 -0.498374 1.170000 -2.787649 1.170000 -5.980957 c -2.830000 -5.980957 l -2.830000 -2.615824 2.316660 -0.155099 1.790166 1.482499 c -1.527114 2.300695 1.261366 2.911589 1.056147 3.325581 c -0.953561 3.532529 0.866165 3.690144 0.801883 3.799746 c -0.769744 3.854543 0.743388 3.897330 0.723805 3.928271 c -0.714015 3.943742 0.705917 3.956251 0.699638 3.965818 c -0.696498 3.970602 0.693813 3.974651 0.691598 3.977967 c -0.690490 3.979625 0.689500 3.981099 0.688629 3.982391 c -0.688194 3.983037 0.687788 3.983638 0.687413 3.984192 c -0.687225 3.984469 0.686966 3.984851 0.686872 3.984990 c -0.686621 3.985360 0.686377 3.985719 0.000000 3.519043 c -h -1.170000 -5.980957 m -1.170000 -9.174265 0.683340 -11.463540 0.209833 -12.936331 c --0.027114 -13.673330 -0.261366 -14.207729 -0.431147 -14.550232 c --0.516061 -14.721529 -0.584915 -14.844961 -0.630008 -14.921844 c --0.652556 -14.960291 -0.669169 -14.987106 -0.678884 -15.002457 c --0.683741 -15.010132 -0.686874 -15.014940 -0.688163 -15.016905 c --0.688808 -15.017887 -0.688991 -15.018158 -0.688699 -15.017719 c --0.688552 -15.017500 -0.688287 -15.017103 -0.687901 -15.016531 c --0.687707 -15.016245 -0.687484 -15.015913 -0.687230 -15.015539 c --0.687103 -15.015350 -0.686890 -15.015036 -0.686827 -15.014942 c --0.686606 -15.014618 -0.686377 -15.014280 0.000000 -15.480957 c -0.686377 -15.947634 0.686621 -15.947273 0.686872 -15.946903 c -0.686966 -15.946766 0.687225 -15.946383 0.687413 -15.946106 c -0.687788 -15.945551 0.688194 -15.944952 0.688629 -15.944305 c -0.689500 -15.943014 0.690490 -15.941538 0.691598 -15.939880 c -0.693813 -15.936565 0.696498 -15.932516 0.699638 -15.927732 c -0.705917 -15.918165 0.714015 -15.905657 0.723805 -15.890184 c -0.743388 -15.859243 0.769744 -15.816458 0.801883 -15.761660 c -0.866165 -15.652058 0.953561 -15.494444 1.056147 -15.287495 c -1.261366 -14.873503 1.527114 -14.262609 1.790166 -13.444414 c -2.316660 -11.806815 2.830000 -9.346090 2.830000 -5.980957 c -1.170000 -5.980957 l -h -f -n -Q - -endstream -endobj - -3 0 obj - 7785 -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 -0000007875 00000 n -0000007898 00000 n -0000008071 00000 n -0000008145 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -8204 -%%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 index 186f60078b..ee96d83980 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "filename" : "ic_search.pdf", + "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/ic_search.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/ic_search.pdf deleted file mode 100644 index 1e6ad4f2b4..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSearchIcon.imageset/ic_search.pdf +++ /dev/null @@ -1,82 +0,0 @@ -%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.999991 4.221268 cm -0.000000 0.000000 0.000000 scn -2.000000 12.278740 m -2.000000 15.868591 4.910149 18.778740 8.500000 18.778740 c -12.089850 18.778740 15.000000 15.868591 15.000000 12.278740 c -15.000000 8.688890 12.089850 5.778740 8.500000 5.778740 c -4.910149 5.778740 2.000000 8.688890 2.000000 12.278740 c -h -8.500000 20.778740 m -3.805580 20.778740 0.000000 16.973160 0.000000 12.278740 c -0.000000 7.584319 3.805580 3.778740 8.500000 3.778740 c -10.427133 3.778740 12.204475 4.420067 13.630243 5.500938 c -18.676220 0.454960 l -19.131182 0.000000 19.868818 0.000000 20.323780 0.454960 c -20.778740 0.909922 20.778740 1.647558 20.323780 2.102520 c -15.277802 7.148497 l -16.358673 8.574265 17.000000 10.351607 17.000000 12.278740 c -17.000000 16.973160 13.194421 20.778740 8.500000 20.778740 c -h -f* -n -Q - -endstream -endobj - -3 0 obj - 864 -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 -0000000954 00000 n -0000000976 00000 n -0000001149 00000 n -0000001223 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -1282 -%%EOF \ No newline at end of file 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 index 6044f8aa11..67a1f22d45 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json @@ -8,5 +8,8 @@ "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "template-rendering-intent" : "template" } } 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 index 0f561e6972..e87af5cac3 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/Contents.json @@ -1,12 +1,15 @@ { "images" : [ { - "filename" : "ic_stickers.pdf", + "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/ic_stickers.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/ic_stickers.pdf deleted file mode 100644 index 24ac31eb23..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputStickersIcon.imageset/ic_stickers.pdf +++ /dev/null @@ -1,431 +0,0 @@ -%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.336044 cm -0.000000 0.000000 0.000000 scn -12.629680 1.768461 m -12.783916 0.952917 l -12.629680 1.768461 l -h -16.593809 4.257765 m -17.180708 3.670866 l -16.593809 4.257765 l -h -14.895066 2.706814 m -14.427451 3.392551 l -14.895066 2.706814 l -h -21.895494 11.034276 m -22.711039 10.880039 l -21.895494 11.034276 l -h -19.406189 7.070145 m -18.819290 7.657043 l -19.406189 7.070145 l -h -20.957142 8.768889 m -20.271404 9.236505 l -20.957142 8.768889 l -h -0.483443 6.107693 m --0.289235 5.804592 l -0.483443 6.107693 l -h -4.443737 2.147398 m -4.140636 1.374722 l -4.443737 2.147398 l -h -21.516558 19.220219 m -22.289234 19.523319 l -21.516558 19.220219 l -h -3.962814 22.970737 m -3.602690 23.718542 l -3.962814 22.970737 l -h -0.693218 19.701141 m --0.054586 20.061266 l -0.693218 19.701141 l -h -11.000000 22.833956 m -11.668203 22.833956 l -11.668203 24.493956 l -11.000000 24.493956 l -11.000000 22.833956 l -h -0.830000 11.995752 m -0.830000 12.663956 l --0.830000 12.663956 l --0.830000 11.995752 l -0.830000 11.995752 l -h -18.819290 7.657043 m -16.006910 4.844664 l -17.180708 3.670866 l -19.993088 6.483246 l -18.819290 7.657043 l -h -10.331797 0.833956 m -11.464174 0.833956 12.137112 0.830593 12.783916 0.952917 c -12.475444 2.584003 l -12.017082 2.497318 11.526485 2.493956 10.331797 2.493956 c -10.331797 0.833956 l -h -16.006910 4.844664 m -15.162139 3.999891 14.812858 3.655367 14.427451 3.392551 c -15.362681 2.021076 l -15.906537 2.391941 16.379997 2.870155 17.180708 3.670866 c -16.006910 4.844664 l -h -12.783916 0.952917 m -13.707870 1.127657 14.585788 1.491302 15.362681 2.021076 c -14.427451 3.392551 l -13.839379 2.991537 13.174834 2.716274 12.475444 2.584003 c -12.783916 0.952917 l -h -21.170000 13.332159 m -21.170000 12.137469 21.166637 11.646873 21.079952 11.188512 c -22.711039 10.880039 l -22.833363 11.526844 22.830000 12.199781 22.830000 13.332159 c -21.170000 13.332159 l -h -19.993088 6.483246 m -20.793798 7.283958 21.272015 7.757419 21.642879 8.301274 c -20.271404 9.236505 l -20.008589 8.851098 19.664062 8.501816 18.819290 7.657043 c -19.993088 6.483246 l -h -21.079952 11.188512 m -20.947681 10.489121 20.672419 9.824576 20.271404 9.236505 c -21.642879 8.301274 l -22.172653 9.078168 22.536299 9.956086 22.711039 10.880039 c -21.079952 11.188512 l -h --0.830000 11.995752 m --0.830000 10.454670 -0.830408 9.259295 -0.767823 8.296148 c --0.704785 7.326029 -0.575355 6.533985 -0.289235 5.804592 c -1.256120 6.410791 l -1.058798 6.913816 0.946507 7.513920 0.888684 8.403788 c -0.830408 9.300627 0.830000 10.433072 0.830000 11.995752 c --0.830000 11.995752 l -h -10.331797 2.493956 m -8.769116 2.493956 7.636671 2.494364 6.739831 2.552639 c -5.849965 2.610462 5.249860 2.722754 4.746836 2.920076 c -4.140636 1.374722 l -4.870029 1.088600 5.662074 0.959171 6.632193 0.896133 c -7.595339 0.833548 8.790714 0.833956 10.331797 0.833956 c -10.331797 2.493956 l -h --0.289235 5.804592 m -0.506586 3.775846 2.111891 2.170542 4.140636 1.374722 c -4.746836 2.920076 l -3.148195 3.547178 1.883223 4.812151 1.256120 6.410791 c --0.289235 5.804592 l -h -11.668203 22.833956 m -13.230883 22.833956 14.363329 22.833548 15.260168 22.775272 c -16.150036 22.717449 16.750139 22.605158 17.253164 22.407835 c -17.859364 23.953190 l -17.129971 24.239311 16.337927 24.368740 15.367807 24.431778 c -14.404661 24.494364 13.209285 24.493956 11.668203 24.493956 c -11.668203 22.833956 l -h -22.830000 13.332159 m -22.830000 14.873241 22.830408 16.068617 22.767822 17.031763 c -22.704784 18.001881 22.575356 18.793926 22.289234 19.523319 c -20.743879 18.917120 l -20.941202 18.414095 21.053493 17.813992 21.111317 16.924124 c -21.169592 16.027285 21.170000 14.894838 21.170000 13.332159 c -22.830000 13.332159 l -h -17.253164 22.407835 m -18.851805 21.780733 20.116777 20.515760 20.743879 18.917120 c -22.289234 19.523319 l -21.493414 21.552065 19.888109 23.157370 17.859364 23.953190 c -17.253164 22.407835 l -h -11.000000 24.493956 m -9.147122 24.493956 7.709934 24.494541 6.557355 24.404799 c -5.395766 24.314354 4.453906 24.128466 3.602690 23.718542 c -4.322937 22.222933 l -4.911203 22.506227 5.622035 22.666948 6.686217 22.749807 c -7.759411 22.833370 9.121075 22.833956 11.000000 22.833956 c -11.000000 24.493956 l -h -0.830000 12.663956 m -0.830000 14.542881 0.830586 15.904545 0.914148 16.977737 c -0.997008 18.041920 1.157728 18.752752 1.441022 19.341019 c --0.054586 20.061266 l --0.464510 19.210049 -0.650399 18.268190 -0.740843 17.106600 c --0.830586 15.954021 -0.830000 14.516833 -0.830000 12.663956 c -0.830000 12.663956 l -h -3.602690 23.718542 m -2.004527 22.948908 0.715049 21.659428 -0.054586 20.061266 c -1.441022 19.341019 l -2.047490 20.600363 3.063593 21.616465 4.322937 22.222933 c -3.602690 23.718542 l -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 14.000000 3.169342 cm -0.000000 0.000000 0.000000 scn -2.895337 1.513170 m -2.155802 1.889982 l -2.895337 1.513170 l -h -2.349067 0.966900 m -2.725879 0.227365 l -2.349067 0.966900 l -h -4.396603 9.526595 m -4.019791 10.266130 l -4.396603 9.526595 l -h -3.304063 8.434055 m -2.564527 8.810867 l -3.304063 8.434055 l -h -11.863758 10.481591 m -11.124223 10.858403 l -11.863758 10.481591 l -h -11.317488 9.935321 m -11.694300 9.195786 l -11.317488 9.935321 l -h -11.170000 12.830658 m -11.170000 11.799080 l -12.830000 11.799080 l -12.830000 12.830658 l -11.170000 12.830658 l -h -10.000000 10.629079 m -7.031581 10.629079 l -7.031581 8.969079 l -10.000000 8.969079 l -10.000000 10.629079 l -h -2.201579 5.799079 m -2.201579 2.830659 l -3.861579 2.830659 l -3.861579 5.799079 l -2.201579 5.799079 l -h -1.031579 1.660658 m -0.000000 1.660658 l -0.000000 0.000658 l -1.031579 0.000658 l -1.031579 1.660658 l -h -2.201579 2.830659 m -2.201579 2.466930 2.200933 2.244051 2.187305 2.077250 c -2.180954 1.999516 2.172969 1.952377 2.166202 1.923643 c -2.162982 1.909968 2.160270 1.901502 2.158613 1.896861 c -2.157021 1.892399 2.156040 1.890450 2.155802 1.889982 c -3.634872 1.136358 l -3.772548 1.406561 3.820568 1.682304 3.841792 1.942073 c -3.862224 2.192151 3.861579 2.494322 3.861579 2.830659 c -2.201579 2.830659 l -h -1.031579 0.000658 m -1.367916 0.000658 1.670086 0.000012 1.920165 0.020445 c -2.179933 0.041669 2.455676 0.089689 2.725879 0.227365 c -1.972255 1.706435 l -1.971787 1.706197 1.969838 1.705216 1.965376 1.703624 c -1.960735 1.701967 1.952269 1.699255 1.938594 1.696035 c -1.909860 1.689268 1.862720 1.681283 1.784988 1.674932 c -1.618186 1.661304 1.395307 1.660658 1.031579 1.660658 c -1.031579 0.000658 l -h -2.155802 1.889982 m -2.115535 1.810954 2.051283 1.746702 1.972255 1.706435 c -2.725879 0.227365 l -3.117256 0.426782 3.435456 0.744981 3.634872 1.136358 c -2.155802 1.889982 l -h -7.031581 10.629079 m -6.345211 10.629079 5.780515 10.629725 5.321996 10.592262 c -4.853787 10.554008 4.423688 10.471928 4.019791 10.266130 c -4.773415 8.787060 l -4.904296 8.853747 5.091620 8.907908 5.457173 8.937775 c -5.832415 8.968433 6.317819 8.969079 7.031581 8.969079 c -7.031581 10.629079 l -h -3.861579 5.799079 m -3.861579 6.512841 3.862224 6.998244 3.892883 7.373486 c -3.922750 7.739038 3.976911 7.926362 4.043598 8.057243 c -2.564527 8.810867 l -2.358731 8.406969 2.276650 7.976871 2.238396 7.508663 c -2.200933 7.050144 2.201579 6.485449 2.201579 5.799079 c -3.861579 5.799079 l -h -4.019791 10.266130 m -3.393211 9.946873 2.883785 9.437447 2.564527 8.810867 c -4.043598 8.057243 l -4.203707 8.371473 4.459184 8.626951 4.773415 8.787060 c -4.019791 10.266130 l -h -11.170000 11.799080 m -11.170000 11.435350 11.169354 11.212472 11.155726 11.045670 c -11.149375 10.967937 11.141390 10.920798 11.134623 10.892064 c -11.131403 10.878389 11.128691 10.869923 11.127034 10.865282 c -11.125442 10.860820 11.124461 10.858871 11.124223 10.858403 c -12.603293 10.104778 l -12.740969 10.374982 12.788989 10.650725 12.810213 10.910493 c -12.830646 11.160572 12.830000 11.462742 12.830000 11.799080 c -11.170000 11.799080 l -h -10.000000 8.969079 m -10.336337 8.969079 10.638507 8.968433 10.888586 8.988866 c -11.148354 9.010090 11.424097 9.058110 11.694300 9.195786 c -10.940676 10.674856 l -10.940208 10.674618 10.938259 10.673637 10.933797 10.672045 c -10.929156 10.670388 10.920690 10.667677 10.907015 10.664455 c -10.878281 10.657689 10.831141 10.649704 10.753409 10.643353 c -10.586607 10.629725 10.363729 10.629079 10.000000 10.629079 c -10.000000 8.969079 l -h -11.124223 10.858403 m -11.083956 10.779375 11.019704 10.715123 10.940676 10.674856 c -11.694300 9.195786 l -12.085677 9.395203 12.403876 9.713402 12.603293 10.104778 c -11.124223 10.858403 l -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 10.000000 16.250000 cm -0.000000 0.000000 0.000000 scn -3.000000 1.750000 m -3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c -0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c -0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c -2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 17.000000 16.250000 cm -0.000000 0.000000 0.000000 scn -3.000000 1.750000 m -3.000000 0.783502 2.328427 0.000000 1.500000 0.000000 c -0.671573 0.000000 0.000000 0.783502 0.000000 1.750000 c -0.000000 2.716498 0.671573 3.500000 1.500000 3.500000 c -2.328427 3.500000 3.000000 2.716498 3.000000 1.750000 c -h -f -n -Q -q -1.000000 0.000000 -0.000000 1.000000 11.000000 8.230942 cm -0.000000 0.000000 0.000000 scn -0.664000 4.267058 m -0.388962 4.633775 -0.131283 4.708096 -0.498000 4.433058 c --0.864717 4.158020 -0.939038 3.637775 -0.664000 3.271058 c -0.664000 4.267058 l -h -4.000000 1.769054 m -3.999999 0.939054 l -4.000000 0.939054 l -4.000000 1.769054 l -h -6.332036 1.389412 m -6.752154 1.572791 6.944070 2.062022 6.760692 2.482140 c -6.577314 2.902259 6.088083 3.094175 5.667964 2.910796 c -6.332036 1.389412 l -h -0.000000 3.769058 m --0.664000 3.271058 -0.663799 3.270791 -0.663593 3.270516 c --0.663516 3.270414 -0.663304 3.270131 -0.663150 3.269927 c --0.662843 3.269519 -0.662512 3.269080 -0.662157 3.268610 c --0.661448 3.267670 -0.660643 3.266607 -0.659743 3.265423 c --0.657943 3.263054 -0.655763 3.260200 -0.653203 3.256877 c --0.648084 3.250230 -0.641445 3.241700 -0.633302 3.231414 c --0.617020 3.210848 -0.594689 3.183217 -0.566423 3.149538 c --0.509945 3.082245 -0.429440 2.990409 -0.325813 2.882277 c --0.119243 2.666726 0.183137 2.382302 0.574317 2.097807 c -1.353481 1.531142 2.521308 0.939057 3.999999 0.939054 c -4.000001 2.599054 l -2.978692 2.599056 2.146519 3.006973 1.550683 3.440309 c -1.254363 3.655814 1.025493 3.871391 0.872688 4.030839 c -0.796627 4.110207 0.740414 4.174622 0.705095 4.216704 c -0.687462 4.237712 0.675126 4.253050 0.668214 4.261781 c -0.664761 4.266143 0.662671 4.268843 0.661961 4.269765 c -0.661607 4.270226 0.661598 4.270240 0.661937 4.269794 c -0.662106 4.269571 0.662363 4.269233 0.662706 4.268778 c -0.662878 4.268550 0.663072 4.268293 0.663288 4.268007 c -0.663395 4.267863 0.663574 4.267626 0.663627 4.267555 c -0.663811 4.267310 0.664000 4.267058 0.000000 3.769058 c -h -4.000000 0.939054 m -4.844985 0.939054 5.627935 1.082078 6.332036 1.389412 c -5.667964 2.910796 l -5.208086 2.710063 4.657703 2.599054 4.000000 2.599054 c -4.000000 0.939054 l -h -f -n -Q - -endstream -endobj - -3 0 obj - 10900 -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 -0000010990 00000 n -0000011014 00000 n -0000011187 00000 n -0000011261 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -11320 -%%EOF \ No newline at end of file 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/PanelFeaturedIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json new file mode 100644 index 0000000000..4a012887e4 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "trending_24.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/trending_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/trending_24.svg new file mode 100644 index 0000000000..347b33ad8b --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/trending_24.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..a306f2cfb1 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "recent_24.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/recent_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/recent_24.svg new file mode 100644 index 0000000000..af321b3e8c --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/recent_24.svg @@ -0,0 +1,3 @@ + + + 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..e8a3780f19 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "favourites_24.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_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_24.svg new file mode 100644 index 0000000000..af8623783e --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_24.svg @@ -0,0 +1,3 @@ + + + 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..5ae583d444 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "trendinggifs_24.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_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24.svg new file mode 100644 index 0000000000..fddeaac987 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24.svg @@ -0,0 +1,3 @@ + + + diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 775821121c..bc7116cc3b 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1604,7 +1604,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 diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index 6decb7096e..ddba531984 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -956,7 +956,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { super.init() - self.topBackgroundExtension = 41.0 + self.topBackgroundExtension = 34.0 self.followsDefaultHeight = true self.view.addSubview(self.entityKeyboardView) @@ -1036,6 +1036,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }, openStickerSettings: { }, + openFeatured: { + }, addGroupAction: { [weak self, weak controllerInteraction] groupId, isPremiumLocked in guard let controllerInteraction = controllerInteraction, let collectionId = groupId.base as? ItemCollectionId else { return @@ -1180,6 +1182,22 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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 @@ -1492,7 +1510,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { transition: mappedTransition, component: AnyComponent(EntityKeyboardComponent( theme: interfaceState.theme, - bottomInset: bottomInset, + containerInsets: UIEdgeInsets(top: 0.0, left: leftInset, bottom: bottomInset, right: rightInset), emojiContent: self.currentInputData.emoji, stickerContent: stickerContent, gifContent: gifContent?.component, @@ -1841,6 +1859,8 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV }, openStickerSettings: { }, + openFeatured: { + }, addGroupAction: { _, _ in }, clearGroup: { _ in diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index d0c9788f9c..1006b9cb06 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -281,7 +281,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) diff --git a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift index d854ea3a58..8b68f2a4ac 100644 --- a/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift +++ b/submodules/WallpaperBackgroundNode/Sources/WallpaperBackgroundNode.swift @@ -111,18 +111,22 @@ private final class EffectImageLayer: SimpleLayer, GradientBackgroundPatternOver 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 = false + useSoftlight = true + useFilter = false } if self.isUsingSoftlight != useSoftlight { self.isUsingSoftlight = useSoftlight - if self.isUsingSoftlight { + if self.isUsingSoftlight && useFilter { self.compositingFilter = "softLightBlendMode" } else { self.compositingFilter = nil @@ -191,18 +195,18 @@ private final class EffectImageLayer: SimpleLayer, GradientBackgroundPatternOver private static var cachedComposedImage: (size: CGSize, patternContentImage: UIImage, backgroundImageHash: String, image: UIImage)? private func updateComposedImage() { - if self.suspendCompositionUpdates { - self.needsCompositionUpdate = true - return - } - switch self.softlightMode { - case .always: + 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 } @@ -840,7 +844,7 @@ final class WallpaperBackgroundNodeImpl: ASDisplayNode, WallpaperBackgroundNode if self.patternImageLayer.contents != nil { self.patternImageLayer.backgroundColor = nil } else { - self.patternImageLayer.backgroundColor = UIColor.black.cgColor + self.patternImageLayer.backgroundColor = nil } } else { self.backgroundColor = nil From 4d1593f2d5d30baea96aa1c5b0a58e572b6be516 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 03:28:44 +0200 Subject: [PATCH 083/113] Add missing animations --- .../Resources/Animations/anim_botToKey.tgs | Bin 0 -> 1774 bytes .../Resources/Animations/anim_keyToBot.tgs | Bin 0 -> 1763 bytes .../Resources/Animations/anim_keyToSmile.tgs | Bin 0 -> 1506 bytes .../Resources/Animations/anim_keyToSticker.tgs | Bin 0 -> 2072 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 submodules/TelegramUI/Resources/Animations/anim_botToKey.tgs create mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToBot.tgs create mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToSmile.tgs create mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToSticker.tgs diff --git a/submodules/TelegramUI/Resources/Animations/anim_botToKey.tgs b/submodules/TelegramUI/Resources/Animations/anim_botToKey.tgs new file mode 100644 index 0000000000000000000000000000000000000000..20939237d65e0771360b3201dd1797e2184878b5 GIT binary patch literal 1774 zcmVWlo*MOBq~+d4U!rNGSjj{b zN0)Up&3PQHZlWn%c5o3Yj=n}ynL_)@T(=vrIoq`#+ug_O#?&GKqWLCmKa$_U{B{29(cYu_$Qpz~GHFu!8a}tpkMgn&rY0+L!UQ~hs5az-m zt`^K@Jm%C`xyF5bhjwz@@P1B{OaU4Agh3WT49+D+;*^?DNuyx?jB0LFwZk3iHCKz9 zB>}I2jy~0Z?5ZU&wzLu`Xs#kR+;y`bH!+S`fEU`$W{F^23LOu`MGd(1JE?Du9%mzx zc+>~zf6@BbQA&kQ;p$AOFR`7Ve;!TS`t$O>zd&}ToE6p_@AX~Rg*|qb{r-5w+RhMK zB2F@vnMtNFpF}c2MnccO$jw|cD+{J;6XxDLDZee+tBHPAH(O}^^vlohCVwr@+g&~R zpjUj7Oy1YK&o`iO1&e&SST{=ySugeFIzrcjgo}k4CbNq>mIE_Pf;q1DOw7GJm|-Fq ziGB#YTo^tRyn7B5J;k7Uw!tZ3jK8kd>+u-h*NdC0)j33|bw-11+I>MvFUVe5(eZzM z-uMLrn;rxq0PAyl*8j%KW{qXh$Kyj=@2;2o5FxEmOj`Z$-wZJEa%)(IY!MnQKUjOX zhv#T1&L0L^*VpEH%t$Xmvlx>o`waY1FSgC)uHHl%#vy@hAyh#6+*DcvrKxcv2=D!W`yo&Rxlx6_+)mX zvlE^D=yaAJpU$!e=q!8HboT8hv!3CJ&fX@S!P!i7Y{qqG$7gUn%R4qB;fc>qe0Jiq z1NkgFKA)+O&;H!5cH4)j?5PPPACW*$=f}s?d7*N~m57C^7|*JX8KKZg@MA8HBdKXS z`_q@4oMqfNdm>vtfOG79TFhhkH^e>mKJ6M9miItVJXXZT!}V}9Z9{o(q9!0-n8i|k z#*)aXcm+O#+f-}iISm3=-RsfT7-z|E<}Ck}bcaBCd<1N$1OUZvL80*XMxPxPecF#+ z9y|KPOMt|!b&UNMm&9ep9u(AJD9Anv+5doo3)ZeUV&I^$xv>X<{21?udt7_kP#mzK zuq>|k66$z+i9Fm(klUBqOjss=hRuXsNy+0>c$x4f&bk=NEM+p6wxD!X278i$5X(xz zGNKb!mKBv0!E#qcOa_e~TMr&IV^rgyka0n$>xBBkQJ?eV*>0k}d$Vs%TQ%5pd07jZ z%a1w&Sc-}8-E#^5uo_~k@LE!o2nPo+#cac>lXhWIek21Key(+`ES-hYo zsA+95qRL&mx=r7M>Z2%_kg|5&dG;NXU*nd%TBo5;bV<{2w2_3?M%%a#1`Q@;naH>g zLkR=5J`EU252eJPRou~7X+i7aaXa&p0sO^;TCf0p4xK^!< zYS;=i11I4Cz2U>jk(0!Dp#c&*Leg*h+TN*Rj=%U8csP2}riGDlrq1U%}aEXmKiNpQRQLo3a-C#$&|@-P>j(EbtL7MDq>W`R+;H9 z#u2i7q6<6;eR}u=$oT0jF=H~yUS5{^0AA4xk&2}}BWn^#R@%Iln35)QGB2yO z2^wOYeoGq+k{Ywv4&xHospC-2Q(|2u{Wea5l;?Zj!9YInN+X(4-Qo(%Kq*}=(h4R$ z(I6eQ2mE4!SC7j^J+2)#M)g5LqEGAc(1cV)+{NQ1q~GsP=D!m%40D)|HjpF)_Axo> zVs$Ag;B=rDUO|4NQ|PF4hlFPt6Hb^Dg%Nc9WZ4-CeFqt*Orpj(ef(5`s0<7%lZ(ML z$RM#65Oqa9>1xI@^7*TOr)ES<*X-lH{`&E^%)bK~i|wcNa-veRaZX=u;|$`>qQ0j8 QT{XY|7Z*CJcgZyX04+~zO8@`> literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Resources/Animations/anim_keyToBot.tgs b/submodules/TelegramUI/Resources/Animations/anim_keyToBot.tgs new file mode 100644 index 0000000000000000000000000000000000000000..2cc3eed1040ecb071672b5497be60d50950139cf GIT binary patch literal 1763 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 Io^K%l0N2s+!2kdN literal 0 HcmV?d00001 diff --git a/submodules/TelegramUI/Resources/Animations/anim_keyToSticker.tgs b/submodules/TelegramUI/Resources/Animations/anim_keyToSticker.tgs new file mode 100644 index 0000000000000000000000000000000000000000..8863943a7d6036c5ea9c41e9e5d27a7024c4c4e9 GIT binary patch literal 2072 zcmV+z2 z=;f(E(c6n*1gfpXTd#Kwt(rCn^6#AsDN*unojR?PqD5j$B!|P9!{N-KlDF0C>b!EI z6{@PMmqT^#WnFFVt8;kl;h|hz{Z^eDT~{~!*xkX5+y2eZ`);^?G45X+#?94jKfwI! z>uZ|W9S;3?sLn4g>uTG*=?8p&I}LAk@Kkj*zNyY_QuyO;v)_S=!$3o~Fyn2t$6plS>zfaUjUSM0&@!xr=%($+e3I z{q>RAAp06+ecc#g3nr5-=(d3mxBJ=ZoE0egLk)s z)@NUQ{^i+E{nfZ1&b~(g&YH8YhyAbjAaDadzwEY$9-%DH&y0Y6egv|s3;_F|L1FhF z^Cd%gDFJh%6H-hVUizn=GBzUTg%ry*e02-xRGAiHX&{nyj}%lF%V`!w(E+I#oh z-Zw=6G}B(!)Sq!_rpR~%1@|-*+!_V{5m1<%%{xvQOwi=mcmx6eGz9z_f$;1I6osI% zMI02Rpb7682jOWbgf$B7M?hh6*3NM-mxCs}UmUc583FSA?hfbOQCTEq-}J+){tQ(f zj#t>PHrufuKq*NcRr+#Uk+Bch6tJO`b2BNL1c2A1gv6W@?D_eQ2FWZ~b$i^NuZQmb zW^)Awq0CWxMr1+v5A3;|aePSqGVv=YUm65UiJfH;bBYA}(@q9ddwXmWB6H}Djkvtu zKMdXO@Nz%gRY(LEw}2hqJV5>`5t{^IB6>%#TgS!agGHG4y}XRDS_Hcr z`rSy2e!>@%w4rb!rBk(!BEn+|i>KWS<{+ul&vTGo9yraaaxbri~1%Px&d zsc~Ln?bgce1te>{nuTQ(42AY);oC&>ly|}!m}u~e7J;P#=G;(gDHOGnNH9Vt38O_D z@SBelfp#E75j?o6q+oWaB5e261m#Y)v%L3077AfOB$&J&kInX^xeZv6wjWhDFh{v! z>A53Ymu3|Fbp72b1)meX1&vC>Q!~jykrwFj@s+HQLN3 zPZlSGv%M+qW}`ucRT1OPDnlQCFpvs+F}P9)%CrGdB4AM{UqqWi$5Po&Mo%`UXp>6V z7B5ax#MW})Dq(2zT_Ch#D}sSI4G^f2V%-P@9XMBO>H%S^YMj}+)HWDixkDSeu|U=n zbUIuRI)KU+?4@%FSh(7Pw4@v$g@$-4O3+Oq0D?+$1agE~vZUw;R#>2D zjl;;Z%aALo?1?IY)%EvNg_18nkd%QOpso)iXCI!aWf7TlX^gZdGE+2b%h(0=GNM## za)dAGAC1rla~TW0q^HmVi!9ciiK610I0SK|R0E-EIePP_Jj+=$ayChAP$?DXWGi9k zVB>6?4g+SJsSVkO^a~0VXj*Kd*=|8aPvn+Q4K6z64zpL_MC~E=vDxMi9#(2BBY{(W zYC}#UxZq$xoLe}tnktls5|vw^5{@?17f%gO4dd4^UH%J6yZ)c8|4Z1qU9$C?zPtWs zxH^IUFNpDum zTC-BpnN_YevO>0FCPzyJrQ%|}r7ihWMOMG`WaZ})f)bo&VbILPC%sMK&PPBGz1&$Lz=f1F1Hh4Ti1 zNIVnXLaP{}Rwsz~0s+-jAx2Izfg>VZgb7XvWtaqu+os!8_28C6H-g8=2!HTbekaOe~*GY-SrV5UeUAKT-g-vFvkU ziVC!IGLypsZXuE`b&_|#Mb->Ll8Q0h2%w1LeKK;X*03Q#L`U2K?r;zsNfcUoZb8Kk zEl9S3|FJg!-Gy2nErp1MCD2VA^P~m#C&obKpPIn)V>;e=y#%v>{ie1p+YZQ?#+!=< zB#yD-Pm~3OB@0mhf4ci1GVmRs(d}Ms`!lEic}j4JAF+m8{!dDm@BRRABNC<(B>(`n CjOg|N literal 0 HcmV?d00001 From ba5d26b36e4de000374e7fc1cf167058b1db9682 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 03:36:13 +0200 Subject: [PATCH 084/113] Fix default selection --- .../Components/EntityKeyboard/Sources/EntityKeyboard.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 23db4e67b5..2185d47d6e 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -375,6 +375,7 @@ public final class EntityKeyboardComponent: Component { contentTopPanels.append(AnyComponentWithIdentity(id: "stickers", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, items: topStickerItems, + defaultActiveItemId: stickerContent.itemGroups.first?.groupId, activeContentItemIdUpdated: stickersContentItemIdUpdated, reorderItems: { [weak self] items in guard let strongSelf = self else { From cb83ca4ec87beeefa175043e07eea63c93b0a345 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 03:44:56 +0200 Subject: [PATCH 085/113] Fix again --- .../EntityKeyboard/Sources/EntityKeyboard.swift | 2 +- .../Sources/EntityKeyboardTopPanelComponent.swift | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 2185d47d6e..ed42e4b1cd 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -285,7 +285,7 @@ public final class EntityKeyboardComponent: Component { contentTopPanels.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, items: topGifItems, - defaultActiveItemId: defaultActiveGifItemId, + forceActiveItemId: defaultActiveGifItemId, activeContentItemIdUpdated: gifsContentItemIdUpdated, reorderItems: { _ in } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 868da96462..c57454cb43 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -996,6 +996,7 @@ final class EntityKeyboardTopPanelComponent: Component { let theme: PresentationTheme let items: [Item] let defaultActiveItemId: AnyHashable? + let forceActiveItemId: AnyHashable? let activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)> let reorderItems: ([Item]) -> Void @@ -1003,12 +1004,14 @@ final class EntityKeyboardTopPanelComponent: Component { theme: PresentationTheme, items: [Item], defaultActiveItemId: AnyHashable? = nil, + forceActiveItemId: AnyHashable? = nil, activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)>, reorderItems: @escaping ([Item]) -> Void ) { self.theme = theme self.items = items self.defaultActiveItemId = defaultActiveItemId + self.forceActiveItemId = forceActiveItemId self.activeContentItemIdUpdated = activeContentItemIdUpdated self.reorderItems = reorderItems } @@ -1023,6 +1026,9 @@ final class EntityKeyboardTopPanelComponent: Component { if lhs.defaultActiveItemId != rhs.defaultActiveItemId { return false } + if lhs.forceActiveItemId != rhs.forceActiveItemId { + return false + } if lhs.activeContentItemIdUpdated !== rhs.activeContentItemIdUpdated { return false } @@ -1594,7 +1600,9 @@ final class EntityKeyboardTopPanelComponent: Component { self.component = component self.state = state - if let defaultActiveItemId = component.defaultActiveItemId { + if let forceActiveItemId = component.forceActiveItemId { + self.activeContentItemId = forceActiveItemId + } else if self.activeContentItemId == nil, let defaultActiveItemId = component.defaultActiveItemId { self.activeContentItemId = defaultActiveItemId } From 6fd38af0fe6ac4b682ce59d2f2c009751146756f Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 15:25:27 +0200 Subject: [PATCH 086/113] Emoji improvements --- .../Sources/Node/ChatListItem.swift | 2 +- .../PendingUpdateMessageManager.swift | 8 +- .../PendingMessages/RequestEditMessage.swift | 16 ++- .../Messages/TelegramEngineMessages.swift | 4 +- .../Resources/PresentationResourcesChat.swift | 2 +- .../Sources/EmojiPagerContentComponent.swift | 114 +++++++++--------- .../EntityKeyboardTopPanelComponent.swift | 33 +++-- .../Contents.json | 12 ++ .../PanelSectionLockIcon.imageset/Locked.svg | 4 + .../TelegramUI/Sources/ChatController.swift | 44 ++++++- .../Sources/ChatControllerNode.swift | 1 + .../Sources/ChatEntityKeyboardInputNode.swift | 19 ++- 12 files changed, 170 insertions(+), 89 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSectionLockIcon.imageset/Locked.svg diff --git a/submodules/ChatListUI/Sources/Node/ChatListItem.swift b/submodules/ChatListUI/Sources/Node/ChatListItem.swift index d61f1342de..564b0569a5 100644 --- a/submodules/ChatListUI/Sources/Node/ChatListItem.swift +++ b/submodules/ChatListUI/Sources/Node/ChatListItem.swift @@ -1200,7 +1200,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode { 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.last { + } else if let message = messages.first { var composedString: NSMutableAttributedString if let peerText = peerText { 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/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/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift index 51d10d9031..b3e6d7d8da 100644 --- a/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift +++ b/submodules/TelegramPresentationData/Sources/Resources/PresentationResourcesChat.swift @@ -1284,7 +1284,7 @@ public struct PresentationResourcesChat { 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/Stickers/SmallLock"), color: color) + return generateTintedImage(image: UIImage(bundleImageName: "Chat/Input/Media/PanelSectionLockIcon"), color: color) }) } } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 41b7ed28e1..eb5f007d65 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -579,7 +579,7 @@ private final class GroupHeaderLayer: UIView { cache: AnimationCache, renderer: MultiAnimationRenderer, attemptSynchronousLoad: Bool - ) -> CGSize { + ) -> (size: CGSize, centralContentWidth: CGFloat) { var themeUpdated = false if self.theme !== theme { self.theme = theme @@ -606,48 +606,8 @@ private final class GroupHeaderLayer: UIView { let titleHorizontalOffset: CGFloat 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.aspectFitted(CGSize(width: 16.0, height: 16.0)) - lockIconLayer.contents = image.cgImage - titleHorizontalOffset = imageSize.width + 2.0 - lockIconLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: imageSize) - } else { - lockIconLayer.contents = nil - titleHorizontalOffset = 0.0 - } - - 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) { - let imageSize = image.size.aspectFitted(CGSize(width: 16.0, height: 16.0)) - tintLockIconLayer.contents = image.cgImage - tintLockIconLayer.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: imageSize) - } else { - tintLockIconLayer.contents = nil - } + titleHorizontalOffset = 10.0 + 2.0 } else { - if let lockIconLayer = self.lockIconLayer { - self.lockIconLayer = nil - lockIconLayer.removeFromSuperlayer() - } - if let tintLockIconLayer = self.tintLockIconLayer { - self.tintLockIconLayer = nil - tintLockIconLayer.removeFromSuperlayer() - } titleHorizontalOffset = 0.0 } @@ -712,15 +672,53 @@ private final class GroupHeaderLayer: UIView { } let textFrame: CGRect - if (layoutType == .compact && hasClear) || subtitle != nil { - textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset, y: textOffsetY), size: textSize) - } else { - textFrame = CGRect(origin: CGPoint(x: floor((constrainedSize.width - textSize.width) / 2.0), y: textOffsetY), size: textSize) - } + textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - textSize.width) / 2.0), 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? @@ -836,11 +834,7 @@ private final class GroupHeaderLayer: UIView { } var size: CGSize - if layoutType == .compact && hasClear { - size = CGSize(width: titleHorizontalOffset + textSize.width + clearWidth, height: constrainedSize.height) - } else { - size = CGSize(width: constrainedSize.width, height: constrainedSize.height) - } + size = CGSize(width: constrainedSize.width, height: constrainedSize.height) if let embeddedItems = embeddedItems { let groupEmbeddedView: GroupEmbeddedView @@ -908,7 +902,7 @@ private final class GroupHeaderLayer: UIView { } } - return size + return (size, titleHorizontalOffset + textSize.width + clearWidth) } override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { @@ -1552,14 +1546,14 @@ public final class EmojiPagerContentComponent: Component { if width >= 420.0 { self.itemInsets = UIEdgeInsets(top: containerInsets.top, left: containerInsets.left + 5.0, bottom: containerInsets.bottom, right: containerInsets.right + 5.0) - self.headerInsets = 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) - self.headerInsets = 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: @@ -3039,7 +3033,7 @@ public final class EmojiPagerContentComponent: Component { assignTopVisibleSubgroupId = true } - var headerSize: CGSize? + var headerCentralContentWidth: CGFloat? var headerSizeUpdated = false if let title = itemGroup.title { validGroupHeaderIds.insert(itemGroup.groupId) @@ -3076,7 +3070,7 @@ public final class EmojiPagerContentComponent: Component { let hasTopSeparator = false - let groupHeaderSize = groupHeaderView.update( + let (groupHeaderSize, centralContentWidth) = groupHeaderView.update( context: component.context, theme: theme, layoutType: itemLayout.layoutType, @@ -3097,11 +3091,11 @@ public final class EmojiPagerContentComponent: Component { 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)) - headerSize = CGSize(width: groupHeaderSize.width, height: groupHeaderSize.height) } let groupBorderRadius: CGFloat = 16.0 @@ -3134,8 +3128,8 @@ public final class EmojiPagerContentComponent: Component { if groupBorderLayer.bounds.size != groupBorderFrame.size || headerSizeUpdated { let headerWidth: CGFloat - if let headerSize = headerSize { - headerWidth = headerSize.width + 14.0 + if let headerCentralContentWidth = headerCentralContentWidth { + headerWidth = headerCentralContentWidth + 14.0 } else { headerWidth = 0.0 } diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index c57454cb43..7286fe13ab 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -185,9 +185,14 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { } else if let titleView = self.titleView { self.titleView = nil if let view = titleView.view { - transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in - view?.removeFromSuperview() - }) + 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() + } } } @@ -392,9 +397,14 @@ final class EntityKeyboardIconTopPanelComponent: Component { } else if let titleView = self.titleView { self.titleView = nil if let view = titleView.view { - transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in - view?.removeFromSuperview() - }) + 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() + } } } @@ -724,9 +734,14 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { } else if let titleView = self.titleView { self.titleView = nil if let view = titleView.view { - transition.setAlpha(view: view, alpha: 0.0, completion: { [weak view] _ in - view?.removeFromSuperview() - }) + 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() + } } } 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/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index e298dea3ac..7f5f65bc9d 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -3090,7 +3090,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 })) } @@ -7105,6 +7107,44 @@ 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 = self.context.sharedContext.currentPresentationData.with { $0 } + //TODO:localize + strongSelf.controllerInteraction?.displayUndo(.sticker(context: strongSelf.context, file: firstLockedPremiumEmoji, title: nil, text: "Subscribe to Telegram Premium to unlock premium emoji.", undoText: "More", 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 { @@ -7121,7 +7161,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) } } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index bc7116cc3b..d9ff15c6ca 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1374,6 +1374,7 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { case .overPanels: self.inputContextPanelContainer.addSubnode(inputContextPanelNode) case .overTextInput: + inputContextPanelNode.view.disablesInteractiveKeyboardGestureRecognizer = true self.inputContextOverTextPanelContainer.addSubnode(inputContextPanelNode) } immediatelyLayoutInputContextPanelAndAnimateAppearance = true diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index ddba531984..a55fcff8de 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -945,6 +945,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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 @@ -973,9 +975,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { |> distinctUntilChanged self.emojiInputInteraction = EmojiPagerContentComponent.InputInteraction( - performItemAction: { [weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in + performItemAction: { [weak self, weak interfaceInteraction, weak controllerInteraction] _, item, _, _, _ in let _ = (hasPremium |> take(1) |> deliverOnMainQueue).start(next: { hasPremium in - guard let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { + guard let strongSelf = self, let controllerInteraction = controllerInteraction, let interfaceInteraction = interfaceInteraction else { return } @@ -994,10 +996,17 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } if file.isPremiumEmoji && !hasPremium { + var animateInAsReplacement = false + if let currentUndoOverlayController = strongSelf.currentUndoOverlayController { + currentUndoOverlayController.dismissWithCommitActionAndReplacementAnimation() + strongSelf.currentUndoOverlayController = nil + animateInAsReplacement = true + } + //TODO:localize let presentationData = context.sharedContext.currentPresentationData.with { $0 } - controllerInteraction.presentController(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { [weak controllerInteraction] in + let controller = UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { [weak controllerInteraction] in guard let controllerInteraction = controllerInteraction else { return } @@ -1014,7 +1023,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { /*let controller = PremiumIntroScreen(context: context, source: .stickers) controllerInteraction.navigationController()?.pushViewController(controller)*/ - }), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), nil) + }), elevatedLayout: false, animateInAsReplacement: animateInAsReplacement, action: { _ in return false }) + strongSelf.currentUndoOverlayController = controller + controllerInteraction.presentController(controller, nil) return } From d09d069ac4830b67456ad4bb0171e31b3d4ce4a2 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 24 Jul 2022 17:03:57 +0300 Subject: [PATCH 087/113] Various fixes --- submodules/Display/Source/WindowContent.swift | 3 +- .../Sources/DeleteAccountDataController.swift | 2 +- .../Animations/anim_channelMute.json | 1 + .../Animations/anim_channelUnmute.json | 1 + .../Sources/ChatTextInputPanelNode.swift | 193 ++++++++++-------- .../Sources/TelegramRootController.swift | 12 +- 6 files changed, 118 insertions(+), 94 deletions(-) create mode 100644 submodules/TelegramUI/Resources/Animations/anim_channelMute.json create mode 100644 submodules/TelegramUI/Resources/Animations/anim_channelUnmute.json diff --git a/submodules/Display/Source/WindowContent.swift b/submodules/Display/Source/WindowContent.swift index e66677cd42..37a8544460 100644 --- a/submodules/Display/Source/WindowContent.swift +++ b/submodules/Display/Source/WindowContent.swift @@ -331,6 +331,7 @@ public class Window1 { self.hostView = hostView self.badgeView = UIImageView() self.badgeView.image = UIImage(bundleImageName: "Components/AppBadge") + self.badgeView.isHidden = true self.systemUserInterfaceStyle = hostView.systemUserInterfaceStyle @@ -655,7 +656,7 @@ public class Window1 { } } - private var forceBadgeHidden = false + private var forceBadgeHidden = true public func setForceBadgeHidden(_ hidden: Bool) { guard hidden != self.forceBadgeHidden else { return 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/TelegramUI/Resources/Animations/anim_channelMute.json b/submodules/TelegramUI/Resources/Animations/anim_channelMute.json new file mode 100644 index 0000000000..5ef523d12f --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/anim_channelUnmute.json b/submodules/TelegramUI/Resources/Animations/anim_channelUnmute.json new file mode 100644 index 0000000000..7000a1a973 --- /dev/null +++ b/submodules/TelegramUI/Resources/Animations/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/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 490d75f2d6..6ad731637f 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -60,7 +60,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.addSubnode(self.iconImageNode) switch item { - case .input, .botInput: + case .input, .botInput, .silentPost: self.iconImageNode.isHidden = true self.animationView = ComponentView() default: @@ -169,104 +169,123 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.iconImageNode.image = AccessoryItemIconButtonNode.imageAndInsets(item: item, theme: self.theme, strings: self.strings).0 let bottomInset: CGFloat = 0.0 + // let iconSize = CGSize(width: 32.0, height: 32.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.iconImageNode.frame = imageFrame if let animationView = self.animationView { - let animationFrame = imageFrame.insetBy(dx: -4.0, dy: -4.0) + let width = AccessoryItemIconButtonNode.calculateWidth(item: item, image: image, text: "", strings: self.strings) - 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" - ] + 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 let inputMode = inputMode { - switch inputMode { - case .keyboard: - if let previousInputMode = previousInputMode { - if case .stickers = previousInputMode { - animationName = "anim_stickerToKey" - animationMode = .animating(loop: false) - } else if case .emoji = previousInputMode { - animationName = "anim_smileToKey" - animationMode = .animating(loop: false) - } else if case .bot = previousInputMode { - animationName = "anim_botToKey" - animationMode = .animating(loop: false) - } else { - animationName = "anim_stickerToKey" - } - } else { - animationName = "anim_stickerToKey" - } - case .stickers: - if let previousInputMode = previousInputMode { - if case .keyboard = previousInputMode { - animationName = "anim_keyToSticker" - animationMode = .animating(loop: false) - } else if case .emoji = previousInputMode { - animationName = "anim_smileToSticker" - animationMode = .animating(loop: false) - colorKeys = emojiColorKeys - } else { - animationName = "anim_keyToSticker" - } - } else { - animationName = "anim_keyToSticker" - } - case .emoji: - if let previousInputMode = previousInputMode { - if case .keyboard = previousInputMode { - animationName = "anim_keyToSmile" - animationMode = .animating(loop: false) - } else if case .stickers = previousInputMode { - animationName = "anim_stickerToSmile" - animationMode = .animating(loop: false) - colorKeys = emojiColorKeys - } else { - animationName = "anim_keyToSmile" - } - } else { - animationName = "anim_keyToSmile" - } - case .bot: - if let previousInputMode = previousInputMode { - if case .keyboard = previousInputMode { - animationName = "anim_keyToBot" - animationMode = .animating(loop: false) - } else { - animationName = "anim_keyToBot" - } - } else { - animationName = "anim_keyToBot" - } + + if case let .silentPost(muted) = item { + if case let .silentPost(previousMuted) = previousItem { + if muted { + animationName = "anim_channelMute" + } else { + animationName = "anim_channelUnmute" + } + if muted != previousMuted { + animationMode = .animating(loop: false) + } + } else { + animationName = "anim_channelMute" } } else { - animationName = "" + 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 = "anim_stickerToKey" + animationMode = .animating(loop: false) + } else if case .emoji = previousInputMode { + animationName = "anim_smileToKey" + animationMode = .animating(loop: false) + } else if case .bot = previousInputMode { + animationName = "anim_botToKey" + animationMode = .animating(loop: false) + } else { + animationName = "anim_stickerToKey" + } + } else { + animationName = "anim_stickerToKey" + } + case .stickers: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "anim_keyToSticker" + animationMode = .animating(loop: false) + } else if case .emoji = previousInputMode { + animationName = "anim_smileToSticker" + animationMode = .animating(loop: false) + colorKeys = emojiColorKeys + } else { + animationName = "anim_keyToSticker" + } + } else { + animationName = "anim_keyToSticker" + } + case .emoji: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "anim_keyToSmile" + animationMode = .animating(loop: false) + } else if case .stickers = previousInputMode { + animationName = "anim_stickerToSmile" + animationMode = .animating(loop: false) + colorKeys = emojiColorKeys + } else { + animationName = "anim_keyToSmile" + } + } else { + animationName = "anim_keyToSmile" + } + case .bot: + if let previousInputMode = previousInputMode { + if case .keyboard = previousInputMode { + animationName = "anim_keyToBot" + animationMode = .animating(loop: false) + } else { + animationName = "anim_keyToBot" + } + } else { + animationName = "anim_keyToBot" + } + } + } else { + animationName = "" + } } - + var colors: [String: UIColor] = [:] for colorKey in colorKeys { colors[colorKey] = self.theme.chat.inputPanel.inputControlColor diff --git a/submodules/TelegramUI/Sources/TelegramRootController.swift b/submodules/TelegramUI/Sources/TelegramRootController.swift index 6957009e80..ab664bfbc6 100644 --- a/submodules/TelegramUI/Sources/TelegramRootController.swift +++ b/submodules/TelegramUI/Sources/TelegramRootController.swift @@ -74,11 +74,13 @@ public final class TelegramRootController: NavigationController { } }) - self.applicationInFocusDisposable = (context.sharedContext.applicationBindings.applicationIsActive - |> distinctUntilChanged - |> deliverOn(Queue.mainQueue())).start(next: { value in - context.sharedContext.mainWindow?.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) { From d7a851d61fa05cc3b2f1c484511f47ad0ffbe447 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 16:14:16 +0200 Subject: [PATCH 088/113] Gif improvements --- .../EntityKeyboardTopPanelComponent.swift | 2 +- .../Sources/GifPagerContentComponent.swift | 43 +++-- .../TelegramUI/Sources/ChatController.swift | 4 +- .../Sources/ChatControllerInteraction.swift | 4 +- .../Sources/ChatEntityKeyboardInputNode.swift | 180 ++++++++++++++++-- .../Sources/ChatMediaInputGifPane.swift | 2 +- .../Sources/ChatMediaInputNode.swift | 4 +- .../Sources/GifPaneSearchContentNode.swift | 2 +- 8 files changed, 201 insertions(+), 40 deletions(-) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 7286fe13ab..1d760286e5 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -1821,7 +1821,7 @@ final class EntityKeyboardTopPanelComponent: Component { } let isRound: Bool - if let string = activeContentItemId.base as? String, (string == "recent" || string == "static") { + if let string = activeContentItemId.base as? String, (string == "recent" || string == "static" || string == "trending") { isRound = true } else { isRound = false diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift index 8171d8976e..2194d5b83f 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/GifPagerContentComponent.swift @@ -134,12 +134,12 @@ public final class GifPagerContentComponent: Component { public final class InputInteraction { public let performItemAction: (Item, UIView, CGRect) -> Void - public let openGifContextMenu: (TelegramMediaFile, UIView, CGRect, ContextGesture, Bool) -> 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 (TelegramMediaFile, UIView, CGRect, ContextGesture, Bool) -> Void, + openGifContextMenu: @escaping (Item, UIView, CGRect, ContextGesture, Bool) -> Void, loadMore: @escaping (String) -> Void ) { self.performItemAction = performItemAction @@ -149,17 +149,22 @@ public final class GifPagerContentComponent: Component { } public final class Item: Equatable { - public let file: TelegramMediaFile + public let file: FileMediaReference + public let contextResult: (ChatContextResultCollection, ChatContextResult)? - public init(file: TelegramMediaFile) { + 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.fileId != rhs.file.fileId { + if lhs.file.media.fileId != rhs.file.media.fileId { + return false + } + if (lhs.contextResult == nil) != (rhs.contextResult != nil) { return false } @@ -242,10 +247,16 @@ public final class GifPagerContentComponent: Component { self.horizontalSpacing = 1.0 self.verticalSpacing = 1.0 - let itemHorizontalSpace = width - self.containerInsets.left - self.containerInsets.right - self.itemSize = floor((width - self.horizontalSpacing * 2.0) / 3.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)) - self.itemsPerRow = Int((itemHorizontalSpace + self.horizontalSpacing) / (self.itemSize + self.horizontalSpacing)) 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) } @@ -265,7 +276,7 @@ public final class GifPagerContentComponent: Component { ) ) - if column == self.itemsPerRow - 1 { + if column == self.itemsPerRow - 1 && index < self.itemCount - 1 { rect.size.width = self.width - self.containerInsets.right - rect.minX } @@ -321,7 +332,7 @@ public final class GifPagerContentComponent: Component { self.item = item self.onUpdateDisplayPlaceholder = onUpdateDisplayPlaceholder - super.init(context: context, file: item?.file, synchronousLoad: attemptSynchronousLoad) + super.init(context: context, file: item?.file.media, synchronousLoad: attemptSynchronousLoad) if item == nil { self.updateDisplayPlaceholder(displayPlaceholder: true, duration: 0.0) @@ -453,6 +464,8 @@ public final class GifPagerContentComponent: Component { 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 { @@ -475,7 +488,7 @@ public final class GifPagerContentComponent: Component { return } let rect = strongSelf.scrollView.convert(itemLayer.frame, to: strongSelf) - component.inputInteraction.openGifContextMenu(item.file, strongSelf, rect, gesture, true) + component.inputInteraction.openGifContextMenu(item, strongSelf, rect, gesture, component.subject == .recent) } } @@ -483,16 +496,16 @@ public final class GifPagerContentComponent: Component { fatalError("init(coder:) has not been implemented") } - private func openGifContextMenu(file: TelegramMediaFile, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { + private func openGifContextMenu(item: Item, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { guard let component = self.component else { return } - component.inputInteraction.openGifContextMenu(file, sourceView, sourceRect, gesture, isSaved) + 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.fileId)] { + 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)) } } @@ -629,7 +642,7 @@ public final class GifPagerContentComponent: Component { let itemId: ItemKey if index < component.items.count { item = component.items[index] - itemId = .media(component.items[index].file.fileId) + itemId = .media(component.items[index].file.media.fileId) } else if component.isLoading || component.loadMoreToken != nil { itemId = .placeholder(index) } else { diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 7f5f65bc9d..a396a9928b 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1741,7 +1741,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 } @@ -1749,7 +1749,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return false } if let _ = strongSelf.presentationInterfaceState.slowmodeState, strongSelf.presentationInterfaceState.subject != .scheduledMessages { - strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceNode.view, sourceRect) + strongSelf.interfaceInteraction?.displaySlowmodeTooltip(sourceView, sourceRect) return false } diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index 95c6a9da12..2267e19977 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -75,7 +75,7 @@ public final class ChatControllerInteraction { let sendMessage: (String) -> Void let sendSticker: (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Bool let sendGif: (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool - let sendBotContextResultAsGif: (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect, 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 @@ -179,7 +179,7 @@ public final class ChatControllerInteraction { sendMessage: @escaping (String) -> Void, sendSticker: @escaping (FileMediaReference, Bool, Bool, String?, Bool, UIView, CGRect, CALayer?) -> Bool, sendGif: @escaping (FileMediaReference, UIView, CGRect, Bool, Bool) -> Bool, - sendBotContextResultAsGif: @escaping (ChatContextResultCollection, ChatContextResult, ASDisplayNode, CGRect, 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, diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index a55fcff8de..a427216356 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -616,7 +616,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let controllerInteraction = controllerInteraction else { return } - let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) + let _ = controllerInteraction.sendGif(item.file, view, rect, false, false) }, openGifContextMenu: { _, _, _, _, _ in }, @@ -776,7 +776,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var items: [GifPagerContentComponent.Item] = [] for gifItem in savedGifs { items.append(GifPagerContentComponent.Item( - file: gifItem.contents.get(RecentMediaItem.self)!.media + file: .savedGif(media: gifItem.contents.get(RecentMediaItem.self)!.media), + contextResult: nil )) } return EntityKeyboardGifContent( @@ -800,7 +801,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { if let trendingGifs = trendingGifs { for file in trendingGifs.files { items.append(GifPagerContentComponent.Item( - file: file.file.media + file: file.file, + contextResult: file.contextResult )) } } else { @@ -829,7 +831,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { if let result = result { for file in result.files { items.append(GifPagerContentComponent.Item( - file: file.file.media + file: file.file, + contextResult: file.contextResult )) } loadMoreToken = result.nextOffset @@ -893,7 +896,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { var existingIds = Set() for item in componentValue.component.items { items.append(item) - existingIds.insert(item.file.fileId) + existingIds.insert(item.file.media.fileId) } var loadMoreToken: String? @@ -904,7 +907,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { continue } existingIds.insert(file.file.media.fileId) - items.append(GifPagerContentComponent.Item(file: file.file.media)) + items.append(GifPagerContentComponent.Item( + file: file.file, + contextResult: file.contextResult + )) } if !result.isComplete { loadMoreToken = result.nextOffset @@ -1392,13 +1398,18 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { guard let controllerInteraction = controllerInteraction else { return } - let _ = controllerInteraction.sendGif(.savedGif(media: item.file), view, rect, false, false) + + 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] file, sourceView, sourceRect, gesture, isSaved in + openGifContextMenu: { [weak self] item, sourceView, sourceRect, gesture, isSaved in guard let strongSelf = self else { return } - strongSelf.openGifContextMenu(file: file, sourceView: sourceView, sourceRect: sourceRect, gesture: gesture, isSaved: isSaved) + 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 { @@ -1602,9 +1613,142 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { return (expandedHeight, 0.0) } - private func openGifContextMenu(file: TelegramMediaFile, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { + private func openGifContextMenu(item: GifPagerContentComponent.Item, sourceView: UIView, sourceRect: CGRect, gesture: ContextGesture, isSaved: Bool) { + let file = item + let canSaveGif: Bool - if file.fileId.namespace == Namespaces.Media.CloudFile { + 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 @@ -1639,15 +1783,19 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { }*/ }))) - /*if let (_, _, _, _, _, _, _, _, interfaceState, _, _, _) = strongSelf.validLayout { + 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: strongSelf.strings.Conversation_SendMessage_SendSilently, icon: { theme in + 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) @@ -1660,7 +1808,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } if isSaved { - items.append(.action(ContextMenuActionItem(text: strongSelf.strings.Conversation_SendMessage_ScheduleMessage, icon: { theme in + 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) @@ -1670,7 +1818,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } } - }*/ + } if isSaved || isGifSaved { items.append(.action(ContextMenuActionItem(text: presentationData.strings.Conversation_ContextMenuDelete, textColor: .destructive, icon: { theme in @@ -1724,7 +1872,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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) - }) + })*/ } } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift b/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift index 288c9d53ba..f8d1b0a914 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputGifPane.swift @@ -236,7 +236,7 @@ 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.view, sourceRect, false, false) } diff --git a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift index e827bb3be6..afc1423c61 100644 --- a/submodules/TelegramUI/Sources/ChatMediaInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatMediaInputNode.swift @@ -1470,7 +1470,7 @@ final class ChatMediaInputNode: ChatInputNode { if isSaved { 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) } }))) @@ -1489,7 +1489,7 @@ final class ChatMediaInputNode: ChatInputNode { 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) + let _ = self?.controllerInteraction.sendBotContextResultAsGif(collection, result, sourceNode.view, sourceRect, true) } }))) } diff --git a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift index 6e55f0cbb4..845e95f258 100644 --- a/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift +++ b/submodules/TelegramUI/Sources/GifPaneSearchContentNode.swift @@ -331,7 +331,7 @@ 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.view, sourceRect, false, false) } From 99207385b15cf8ffef50215f16b3173b4420ac59 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 16:23:12 +0200 Subject: [PATCH 089/113] Emoji improvements --- .../Sources/DefaultDayPresentationTheme.swift | 2 +- .../EntityKeyboard/Sources/EntityKeyboard.swift | 5 ++++- .../Sources/EntityKeyboardTopPanelComponent.swift | 14 +++++++++++--- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index 3ad0c85faa..bc6bb3a410 100644 --- a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift +++ b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift @@ -863,7 +863,7 @@ public func makeDefaultDayPresentationTheme(extendingThemeReference: Presentatio 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.6, alpha: 0.65), + 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), diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index ed42e4b1cd..738ed544e1 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -285,6 +285,7 @@ public final class EntityKeyboardComponent: Component { contentTopPanels.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(EntityKeyboardTopPanelComponent( theme: component.theme, items: topGifItems, + containerSideInset: component.containerInsets.left, forceActiveItemId: defaultActiveGifItemId, activeContentItemIdUpdated: gifsContentItemIdUpdated, reorderItems: { _ in @@ -352,7 +353,7 @@ public final class EntityKeyboardComponent: Component { if let file = itemGroup.items[0].file { topStickerItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.supergroupId, - isReorderable: true, + isReorderable: !itemGroup.isFeatured, content: AnyComponent(EntityKeyboardAnimationTopPanelComponent( context: stickerContent.context, file: file, @@ -375,6 +376,7 @@ public final class EntityKeyboardComponent: Component { 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 @@ -478,6 +480,7 @@ public final class EntityKeyboardComponent: Component { 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 { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 1d760286e5..9028825dd1 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -1010,6 +1010,7 @@ final class EntityKeyboardTopPanelComponent: Component { let theme: PresentationTheme let items: [Item] + let containerSideInset: CGFloat let defaultActiveItemId: AnyHashable? let forceActiveItemId: AnyHashable? let activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)> @@ -1018,6 +1019,7 @@ final class EntityKeyboardTopPanelComponent: Component { init( theme: PresentationTheme, items: [Item], + containerSideInset: CGFloat, defaultActiveItemId: AnyHashable? = nil, forceActiveItemId: AnyHashable? = nil, activeContentItemIdUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)>, @@ -1025,6 +1027,7 @@ final class EntityKeyboardTopPanelComponent: Component { ) { self.theme = theme self.items = items + self.containerSideInset = containerSideInset self.defaultActiveItemId = defaultActiveItemId self.forceActiveItemId = forceActiveItemId self.activeContentItemIdUpdated = activeContentItemIdUpdated @@ -1038,6 +1041,9 @@ final class EntityKeyboardTopPanelComponent: Component { if lhs.items != rhs.items { return false } + if lhs.containerSideInset != rhs.containerSideInset { + return false + } if lhs.defaultActiveItemId != rhs.defaultActiveItemId { return false } @@ -1064,7 +1070,7 @@ final class EntityKeyboardTopPanelComponent: Component { } let topInset: CGFloat = -3.0 - let sideInset: CGFloat = 7.0 + let sideInset: CGFloat let itemSize: CGSize let staticItemSize: CGSize let staticExpandedItemSize: CGSize @@ -1074,7 +1080,9 @@ final class EntityKeyboardTopPanelComponent: Component { let isExpanded: Bool let items: [Item] - init(isExpanded: Bool, height: CGFloat, items: [ItemDescription]) { + 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 @@ -1665,7 +1673,7 @@ final class EntityKeyboardTopPanelComponent: Component { } let previousItemLayout = self.itemLayout - let itemLayout = ItemLayout(isExpanded: isExpanded, height: availableSize.height, items: self.items.map { item -> ItemLayout.ItemDescription in + 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, From ea6929fef6cc15753f11766736551c4982fe1331 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 17:31:47 +0200 Subject: [PATCH 090/113] Emoji improvements --- .../Telegram-iOS/en.lproj/Localizable.strings | 17 +++++ ...ArchivedStickerPacksNoticeController.swift | 10 ++- .../AttachmentTextInputPanelNode.swift | 22 ++++++ .../Sources/PagerComponent.swift | 1 + .../ContainedViewLayoutTransition.swift | 8 +-- submodules/Display/Source/NavigationBar.swift | 2 +- .../ArchivedStickerPacksController.swift | 11 ++- .../FeaturedStickerPacksController.swift | 12 +++- .../InstalledStickerPacksController.swift | 70 ++++++++++++++++--- .../Sources/ChatControllerNode.swift | 8 +-- .../Sources/ChatHistoryEntriesForView.swift | 2 +- .../Sources/ChatTextInputPanelNode.swift | 48 ++++++++++--- .../Sources/TouchDownGestureRecognizer.swift | 22 +++--- 13 files changed, 191 insertions(+), 42 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 0c3d34a763..f208f82f9f 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7883,8 +7883,13 @@ Sorry for the inconvenience."; "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."; +"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$@**?"; @@ -7893,3 +7898,15 @@ Sorry for the inconvenience."; "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."; diff --git a/submodules/ArchivedStickerPacksNotice/Sources/ArchivedStickerPacksNoticeController.swift b/submodules/ArchivedStickerPacksNotice/Sources/ArchivedStickerPacksNoticeController.swift index bacd63fd78..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 } diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index ae4ea05956..ab164cbba7 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -405,6 +405,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 + } + } self.textInputBackgroundNode.view.addGestureRecognizer(recognizer) self.emojiViewProvider = { [weak self] emoji in @@ -525,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 diff --git a/submodules/Components/PagerComponent/Sources/PagerComponent.swift b/submodules/Components/PagerComponent/Sources/PagerComponent.swift index a020e249f8..f5d31dfa3a 100644 --- a/submodules/Components/PagerComponent/Sources/PagerComponent.swift +++ b/submodules/Components/PagerComponent/Sources/PagerComponent.swift @@ -430,6 +430,7 @@ public final class PagerComponent() @@ -437,7 +437,8 @@ final class CustomEmojiContainerView: UIView { continue } - let size = CGSize(width: 24.0, height: 24.0) + 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) @@ -896,6 +897,17 @@ 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) @@ -992,6 +1004,26 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { 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) self.touchDownGestureRecognizer = recognizer @@ -1081,14 +1113,6 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { 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, isMediaInputExpanded) - - let textFieldWaitsForTouchUp: Bool - if case .regular = metrics.widthClass, bottomInset.isZero { - textFieldWaitsForTouchUp = true - } else { - textFieldWaitsForTouchUp = false - } - self.touchDownGestureRecognizer?.waitForTouchUp = textFieldWaitsForTouchUp var transition = transition var additionalOffset: CGFloat = 0.0 @@ -2146,6 +2170,8 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { var rects: [CGRect] = [] var customEmojiRects: [(CGRect, ChatTextInputTextCustomEmojiAttribute)] = [] + let fontSize = max(minInputFontSize, presentationInterfaceState.fontSize.baseDisplaySize) + if let attributedText = textInputNode.attributedText { let beginning = textInputNode.textView.beginningOfDocument attributedText.enumerateAttributes(in: NSMakeRange(0, attributedText.length), options: [], using: { attributes, range, _ in @@ -2229,7 +2255,7 @@ class ChatTextInputPanelNode: ChatInputPanelNode, ASEditableTextNodeDelegate { self.customEmojiContainerView = customEmojiContainerView } - customEmojiContainerView.update(emojiRects: customEmojiRects) + customEmojiContainerView.update(fontSize: fontSize, emojiRects: customEmojiRects) } else if let customEmojiContainerView = self.customEmojiContainerView { customEmojiContainerView.removeFromSuperview() self.customEmojiContainerView = nil 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() - } } From df6e87cc3d1597bdd2ca7986ad56cb7c638ecd79 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 18:18:59 +0200 Subject: [PATCH 091/113] Emoji fixes --- .../Sources/AnimationCache.swift | 4 ++ .../Resources/Animations/anim_botToKey.tgs | Bin 1774 -> 0 bytes .../Resources/Animations/anim_keyToBot.tgs | Bin 1763 -> 0 bytes .../Resources/Animations/anim_keyToSmile.tgs | Bin 1506 -> 0 bytes .../Animations/anim_keyToSticker.tgs | Bin 2072 -> 0 bytes ...botToKey.json => input_anim_botToKey.json} | 0 ...keyToBot.json => input_anim_keyToBot.json} | 0 ...oSmile.json => input_anim_keyToSmile.json} | 0 ...cker.json => input_anim_keyToSticker.json} | 0 ...eToKey.json => input_anim_smileToKey.json} | 0 ...er.json => input_anim_smileToSticker.json} | 0 ...oKey.json => input_anim_stickerToKey.json} | 0 ...le.json => input_anim_stickerToSmile.json} | 0 .../Sources/ChatTextInputPanelNode.swift | 32 ++++----- .../Source/UIKitRuntimeUtils/UIKitUtils.m | 63 +++++++----------- 15 files changed, 44 insertions(+), 55 deletions(-) delete mode 100644 submodules/TelegramUI/Resources/Animations/anim_botToKey.tgs delete mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToBot.tgs delete mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToSmile.tgs delete mode 100644 submodules/TelegramUI/Resources/Animations/anim_keyToSticker.tgs rename submodules/TelegramUI/Resources/Animations/{anim_botToKey.json => input_anim_botToKey.json} (100%) rename submodules/TelegramUI/Resources/Animations/{anim_keyToBot.json => input_anim_keyToBot.json} (100%) rename submodules/TelegramUI/Resources/Animations/{anim_keyToSmile.json => input_anim_keyToSmile.json} (100%) rename submodules/TelegramUI/Resources/Animations/{anim_keyToSticker.json => input_anim_keyToSticker.json} (100%) rename submodules/TelegramUI/Resources/Animations/{anim_smileToKey.json => input_anim_smileToKey.json} (100%) rename submodules/TelegramUI/Resources/Animations/{anim_smiletosticker.json => input_anim_smileToSticker.json} (100%) rename submodules/TelegramUI/Resources/Animations/{anim_stickerToKey.json => input_anim_stickerToKey.json} (100%) rename submodules/TelegramUI/Resources/Animations/{anim_stickertosmile.json => input_anim_stickerToSmile.json} (100%) diff --git a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift index efb5fd4379..93d442d7f9 100644 --- a/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift +++ b/submodules/TelegramUI/Components/AnimationCache/Sources/AnimationCache.swift @@ -456,6 +456,10 @@ private final class AnimationCacheItemWriterImpl: AnimationCacheItemWriter { } 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 } diff --git a/submodules/TelegramUI/Resources/Animations/anim_botToKey.tgs b/submodules/TelegramUI/Resources/Animations/anim_botToKey.tgs deleted file mode 100644 index 20939237d65e0771360b3201dd1797e2184878b5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1774 zcmVWlo*MOBq~+d4U!rNGSjj{b zN0)Up&3PQHZlWn%c5o3Yj=n}ynL_)@T(=vrIoq`#+ug_O#?&GKqWLCmKa$_U{B{29(cYu_$Qpz~GHFu!8a}tpkMgn&rY0+L!UQ~hs5az-m zt`^K@Jm%C`xyF5bhjwz@@P1B{OaU4Agh3WT49+D+;*^?DNuyx?jB0LFwZk3iHCKz9 zB>}I2jy~0Z?5ZU&wzLu`Xs#kR+;y`bH!+S`fEU`$W{F^23LOu`MGd(1JE?Du9%mzx zc+>~zf6@BbQA&kQ;p$AOFR`7Ve;!TS`t$O>zd&}ToE6p_@AX~Rg*|qb{r-5w+RhMK zB2F@vnMtNFpF}c2MnccO$jw|cD+{J;6XxDLDZee+tBHPAH(O}^^vlohCVwr@+g&~R zpjUj7Oy1YK&o`iO1&e&SST{=ySugeFIzrcjgo}k4CbNq>mIE_Pf;q1DOw7GJm|-Fq ziGB#YTo^tRyn7B5J;k7Uw!tZ3jK8kd>+u-h*NdC0)j33|bw-11+I>MvFUVe5(eZzM z-uMLrn;rxq0PAyl*8j%KW{qXh$Kyj=@2;2o5FxEmOj`Z$-wZJEa%)(IY!MnQKUjOX zhv#T1&L0L^*VpEH%t$Xmvlx>o`waY1FSgC)uHHl%#vy@hAyh#6+*DcvrKxcv2=D!W`yo&Rxlx6_+)mX zvlE^D=yaAJpU$!e=q!8HboT8hv!3CJ&fX@S!P!i7Y{qqG$7gUn%R4qB;fc>qe0Jiq z1NkgFKA)+O&;H!5cH4)j?5PPPACW*$=f}s?d7*N~m57C^7|*JX8KKZg@MA8HBdKXS z`_q@4oMqfNdm>vtfOG79TFhhkH^e>mKJ6M9miItVJXXZT!}V}9Z9{o(q9!0-n8i|k z#*)aXcm+O#+f-}iISm3=-RsfT7-z|E<}Ck}bcaBCd<1N$1OUZvL80*XMxPxPecF#+ z9y|KPOMt|!b&UNMm&9ep9u(AJD9Anv+5doo3)ZeUV&I^$xv>X<{21?udt7_kP#mzK zuq>|k66$z+i9Fm(klUBqOjss=hRuXsNy+0>c$x4f&bk=NEM+p6wxD!X278i$5X(xz zGNKb!mKBv0!E#qcOa_e~TMr&IV^rgyka0n$>xBBkQJ?eV*>0k}d$Vs%TQ%5pd07jZ z%a1w&Sc-}8-E#^5uo_~k@LE!o2nPo+#cac>lXhWIek21Key(+`ES-hYo zsA+95qRL&mx=r7M>Z2%_kg|5&dG;NXU*nd%TBo5;bV<{2w2_3?M%%a#1`Q@;naH>g zLkR=5J`EU252eJPRou~7X+i7aaXa&p0sO^;TCf0p4xK^!< zYS;=i11I4Cz2U>jk(0!Dp#c&*Leg*h+TN*Rj=%U8csP2}riGDlrq1U%}aEXmKiNpQRQLo3a-C#$&|@-P>j(EbtL7MDq>W`R+;H9 z#u2i7q6<6;eR}u=$oT0jF=H~yUS5{^0AA4xk&2}}BWn^#R@%Iln35)QGB2yO z2^wOYeoGq+k{Ywv4&xHospC-2Q(|2u{Wea5l;?Zj!9YInN+X(4-Qo(%Kq*}=(h4R$ z(I6eQ2mE4!SC7j^J+2)#M)g5LqEGAc(1cV)+{NQ1q~GsP=D!m%40D)|HjpF)_Axo> zVs$Ag;B=rDUO|4NQ|PF4hlFPt6Hb^Dg%Nc9WZ4-CeFqt*Orpj(ef(5`s0<7%lZ(ML z$RM#65Oqa9>1xI@^7*TOr)ES<*X-lH{`&E^%)bK~i|wcNa-veRaZX=u;|$`>qQ0j8 QT{XY|7Z*CJcgZyX04+~zO8@`> diff --git a/submodules/TelegramUI/Resources/Animations/anim_keyToBot.tgs b/submodules/TelegramUI/Resources/Animations/anim_keyToBot.tgs deleted file mode 100644 index 2cc3eed1040ecb071672b5497be60d50950139cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1763 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 Io^K%l0N2s+!2kdN diff --git a/submodules/TelegramUI/Resources/Animations/anim_keyToSticker.tgs b/submodules/TelegramUI/Resources/Animations/anim_keyToSticker.tgs deleted file mode 100644 index 8863943a7d6036c5ea9c41e9e5d27a7024c4c4e9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2072 zcmV+z2 z=;f(E(c6n*1gfpXTd#Kwt(rCn^6#AsDN*unojR?PqD5j$B!|P9!{N-KlDF0C>b!EI z6{@PMmqT^#WnFFVt8;kl;h|hz{Z^eDT~{~!*xkX5+y2eZ`);^?G45X+#?94jKfwI! z>uZ|W9S;3?sLn4g>uTG*=?8p&I}LAk@Kkj*zNyY_QuyO;v)_S=!$3o~Fyn2t$6plS>zfaUjUSM0&@!xr=%($+e3I z{q>RAAp06+ecc#g3nr5-=(d3mxBJ=ZoE0egLk)s z)@NUQ{^i+E{nfZ1&b~(g&YH8YhyAbjAaDadzwEY$9-%DH&y0Y6egv|s3;_F|L1FhF z^Cd%gDFJh%6H-hVUizn=GBzUTg%ry*e02-xRGAiHX&{nyj}%lF%V`!w(E+I#oh z-Zw=6G}B(!)Sq!_rpR~%1@|-*+!_V{5m1<%%{xvQOwi=mcmx6eGz9z_f$;1I6osI% zMI02Rpb7682jOWbgf$B7M?hh6*3NM-mxCs}UmUc583FSA?hfbOQCTEq-}J+){tQ(f zj#t>PHrufuKq*NcRr+#Uk+Bch6tJO`b2BNL1c2A1gv6W@?D_eQ2FWZ~b$i^NuZQmb zW^)Awq0CWxMr1+v5A3;|aePSqGVv=YUm65UiJfH;bBYA}(@q9ddwXmWB6H}Djkvtu zKMdXO@Nz%gRY(LEw}2hqJV5>`5t{^IB6>%#TgS!agGHG4y}XRDS_Hcr z`rSy2e!>@%w4rb!rBk(!BEn+|i>KWS<{+ul&vTGo9yraaaxbri~1%Px&d zsc~Ln?bgce1te>{nuTQ(42AY);oC&>ly|}!m}u~e7J;P#=G;(gDHOGnNH9Vt38O_D z@SBelfp#E75j?o6q+oWaB5e261m#Y)v%L3077AfOB$&J&kInX^xeZv6wjWhDFh{v! z>A53Ymu3|Fbp72b1)meX1&vC>Q!~jykrwFj@s+HQLN3 zPZlSGv%M+qW}`ucRT1OPDnlQCFpvs+F}P9)%CrGdB4AM{UqqWi$5Po&Mo%`UXp>6V z7B5ax#MW})Dq(2zT_Ch#D}sSI4G^f2V%-P@9XMBO>H%S^YMj}+)HWDixkDSeu|U=n zbUIuRI)KU+?4@%FSh(7Pw4@v$g@$-4O3+Oq0D?+$1agE~vZUw;R#>2D zjl;;Z%aALo?1?IY)%EvNg_18nkd%QOpso)iXCI!aWf7TlX^gZdGE+2b%h(0=GNM## za)dAGAC1rla~TW0q^HmVi!9ciiK610I0SK|R0E-EIePP_Jj+=$ayChAP$?DXWGi9k zVB>6?4g+SJsSVkO^a~0VXj*Kd*=|8aPvn+Q4K6z64zpL_MC~E=vDxMi9#(2BBY{(W zYC}#UxZq$xoLe}tnktls5|vw^5{@?17f%gO4dd4^UH%J6yZ)c8|4Z1qU9$C?zPtWs zxH^IUFNpDum zTC-BpnN_YevO>0FCPzyJrQ%|}r7ihWMOMG`WaZ})f)bo&VbILPC%sMK&PPBGz1&$Lz=f1F1Hh4Ti1 zNIVnXLaP{}Rwsz~0s+-jAx2Izfg>VZgb7XvWtaqu+os!8_28C6H-g8=2!HTbekaOe~*GY-SrV5UeUAKT-g-vFvkU ziVC!IGLypsZXuE`b&_|#Mb->Ll8Q0h2%w1LeKK;X*03Q#L`U2K?r;zsNfcUoZb8Kk zEl9S3|FJg!-Gy2nErp1MCD2VA^P~m#C&obKpPIn)V>;e=y#%v>{ie1p+YZQ?#+!=< zB#yD-Pm~3OB@0mhf4ci1GVmRs(d}Ms`!lEic}j4JAF+m8{!dDm@BRRABNC<(B>(`n CjOg|N diff --git a/submodules/TelegramUI/Resources/Animations/anim_botToKey.json b/submodules/TelegramUI/Resources/Animations/input_anim_botToKey.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_botToKey.json rename to submodules/TelegramUI/Resources/Animations/input_anim_botToKey.json diff --git a/submodules/TelegramUI/Resources/Animations/anim_keyToBot.json b/submodules/TelegramUI/Resources/Animations/input_anim_keyToBot.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_keyToBot.json rename to submodules/TelegramUI/Resources/Animations/input_anim_keyToBot.json diff --git a/submodules/TelegramUI/Resources/Animations/anim_keyToSmile.json b/submodules/TelegramUI/Resources/Animations/input_anim_keyToSmile.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_keyToSmile.json rename to submodules/TelegramUI/Resources/Animations/input_anim_keyToSmile.json diff --git a/submodules/TelegramUI/Resources/Animations/anim_keyToSticker.json b/submodules/TelegramUI/Resources/Animations/input_anim_keyToSticker.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_keyToSticker.json rename to submodules/TelegramUI/Resources/Animations/input_anim_keyToSticker.json diff --git a/submodules/TelegramUI/Resources/Animations/anim_smileToKey.json b/submodules/TelegramUI/Resources/Animations/input_anim_smileToKey.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_smileToKey.json rename to submodules/TelegramUI/Resources/Animations/input_anim_smileToKey.json diff --git a/submodules/TelegramUI/Resources/Animations/anim_smiletosticker.json b/submodules/TelegramUI/Resources/Animations/input_anim_smileToSticker.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_smiletosticker.json rename to submodules/TelegramUI/Resources/Animations/input_anim_smileToSticker.json diff --git a/submodules/TelegramUI/Resources/Animations/anim_stickerToKey.json b/submodules/TelegramUI/Resources/Animations/input_anim_stickerToKey.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_stickerToKey.json rename to submodules/TelegramUI/Resources/Animations/input_anim_stickerToKey.json diff --git a/submodules/TelegramUI/Resources/Animations/anim_stickertosmile.json b/submodules/TelegramUI/Resources/Animations/input_anim_stickerToSmile.json similarity index 100% rename from submodules/TelegramUI/Resources/Animations/anim_stickertosmile.json rename to submodules/TelegramUI/Resources/Animations/input_anim_stickerToSmile.json diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 8656ef430b..a5986e03e5 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -207,60 +207,60 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { case .keyboard: if let previousInputMode = previousInputMode { if case .stickers = previousInputMode { - animationName = "anim_stickerToKey" + animationName = "input_anim_stickerToKey" animationMode = .animating(loop: false) } else if case .emoji = previousInputMode { - animationName = "anim_smileToKey" + animationName = "input_anim_smileToKey" animationMode = .animating(loop: false) } else if case .bot = previousInputMode { - animationName = "anim_botToKey" + animationName = "input_anim_botToKey" animationMode = .animating(loop: false) } else { - animationName = "anim_stickerToKey" + animationName = "input_anim_stickerToKey" } } else { - animationName = "anim_stickerToKey" + animationName = "input_anim_stickerToKey" } case .stickers: if let previousInputMode = previousInputMode { if case .keyboard = previousInputMode { - animationName = "anim_keyToSticker" + animationName = "input_anim_keyToSticker" animationMode = .animating(loop: false) } else if case .emoji = previousInputMode { - animationName = "anim_smileToSticker" + animationName = "input_anim_smileToSticker" animationMode = .animating(loop: false) colorKeys = emojiColorKeys } else { - animationName = "anim_keyToSticker" + animationName = "input_anim_keyToSticker" } } else { - animationName = "anim_keyToSticker" + animationName = "input_anim_keyToSticker" } case .emoji: if let previousInputMode = previousInputMode { if case .keyboard = previousInputMode { - animationName = "anim_keyToSmile" + animationName = "input_anim_keyToSmile" animationMode = .animating(loop: false) } else if case .stickers = previousInputMode { - animationName = "anim_stickerToSmile" + animationName = "input_anim_stickerToSmile" animationMode = .animating(loop: false) colorKeys = emojiColorKeys } else { - animationName = "anim_keyToSmile" + animationName = "input_anim_keyToSmile" } } else { - animationName = "anim_keyToSmile" + animationName = "input_anim_keyToSmile" } case .bot: if let previousInputMode = previousInputMode { if case .keyboard = previousInputMode { - animationName = "anim_keyToBot" + animationName = "input_anim_keyToBot" animationMode = .animating(loop: false) } else { - animationName = "anim_keyToBot" + animationName = "input_anim_keyToBot" } } else { - animationName = "anim_keyToBot" + animationName = "input_anim_keyToBot" } } } else { 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; } From 68ab84bed46b7861ec7c1dcdb8de11470c537631 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 19:10:37 +0200 Subject: [PATCH 092/113] Don't apply animation if not yet finished --- .../Sources/LottieAnimationComponent.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift index ea7b60c4dd..c584daf0e8 100644 --- a/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift +++ b/submodules/Components/LottieAnimationComponent/Sources/LottieAnimationComponent.swift @@ -141,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 @@ -154,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)) From 58c710200729e376a0a9e8d19f583606b47dcc61 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 20:23:40 +0200 Subject: [PATCH 093/113] Fix text input layout --- .../Source/ASTextKitComponents.mm | 4 +++- .../Sources/ChatTextInputPanelNode.swift | 16 +++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm index 7bfee153fa..bba12025a8 100644 --- a/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm +++ b/submodules/AsyncDisplayKit/Source/ASTextKitComponents.mm @@ -172,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/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index a5986e03e5..928cadb6c7 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -581,13 +581,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 { @@ -624,6 +618,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 From c95c59661aea64547279fff251375e20444f4338 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 20:55:19 +0200 Subject: [PATCH 094/113] Emoji improvements --- .../Sources/EmojiPagerContentComponent.swift | 34 ++++++++++++++++--- .../EntityKeyboardTopPanelComponent.swift | 10 ++++-- .../Sources/MultiAnimationRenderer.swift | 29 +++++++++++----- .../ChatInterfaceStateContextQueries.swift | 4 ++- .../Sources/ChatTextInputPanelNode.swift | 14 ++++---- 5 files changed, 68 insertions(+), 23 deletions(-) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index eb5f007d65..f36990b98a 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -1205,7 +1205,11 @@ private final class GroupExpandActionButton: UIButton { self.currentTextLayout = (title, color, textConstrainedWidth, textSize) } - let size = CGSize(width: textSize.width + 10.0 * 2.0, height: 28.0) + 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 @@ -2834,6 +2838,7 @@ public final class EmojiPagerContentComponent: Component { 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 @@ -3019,8 +3024,16 @@ public final class EmojiPagerContentComponent: Component { let contentAnimation = transition.userData(ContentAnimation.self) var transitionHintInstalledGroupId: AnyHashable? - if let contentAnimation = contentAnimation, case let .groupInstalled(groupId) = contentAnimation.type { - transitionHintInstalledGroupId = groupId + 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) { @@ -3504,8 +3517,19 @@ public final class EmojiPagerContentComponent: Component { for (id, button) in self.visibleGroupExpandActionButtons { if !validGroupExpandActionButtons.contains(id) { removedGroupExpandActionButtonIds.append(id) - button.removeFromSuperview() - button.tintContainerLayer.removeFromSuperlayer() + + 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 { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 9028825dd1..694a8b0956 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -700,7 +700,7 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { 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, dy: 0.0), animated: true) + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -itemLayout.sideInset - (itemLayout.itemSpacing + itemFrame.width) * 2.0, dy: 0.0), animated: true) break } } @@ -1898,7 +1898,13 @@ final class EntityKeyboardTopPanelComponent: Component { for i in 0 ..< component.items.count { if component.items[i].id == itemId { let itemFrame = itemLayout.containerFrame(at: i) - self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: -2.0, dy: 0.0), animated: true) + let expandedInset: CGFloat + if itemLayout.isExpanded { + expandedInset = -2.0 + } else { + expandedInset = -itemLayout.sideInset - (itemFrame.width + itemLayout.itemSpacing) * 2.0 + } + self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: expandedInset, dy: 0.0), animated: true) break } } diff --git a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift index 126894163b..85d5dc1f55 100644 --- a/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift +++ b/submodules/TelegramUI/Components/MultiAnimationRenderer/Sources/MultiAnimationRenderer.swift @@ -535,26 +535,37 @@ public final class MultiAnimationRendererImpl: MultiAnimationRenderer { private var groupContext: GroupContext? private var frameSkip: Int - private var displayLink: ConstantDisplayLinkAnimator? + 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 = self.frameSkip - 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() } } } diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift index b4dc54ec9c..4971c3243e 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateContextQueries.swift @@ -376,7 +376,9 @@ private func updatedContextQueryResultStateForQuery(context: AccountContext, pee switch attribute { case let .CustomEmoji(_, alt, _): if !alt.isEmpty, let keyword = allEmoticons[alt] { - result.append((alt, item.file, keyword)) + if !item.file.isPremiumEmoji || hasPremium { + result.append((alt, item.file, keyword)) + } } default: break diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 928cadb6c7..6d5a77b118 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -60,11 +60,11 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.addSubnode(self.iconImageNode) switch item { - case .input, .botInput: - self.iconImageNode.isHidden = true - self.animationView = ComponentView() - default: - break + case .input, .botInput: + self.iconImageNode.isHidden = true + self.animationView = ComponentView() + default: + break } if let text = text { @@ -84,9 +84,11 @@ 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 } } } @@ -269,7 +271,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { var colors: [String: UIColor] = [:] for colorKey in colorKeys { - colors[colorKey] = self.theme.chat.inputPanel.inputControlColor + colors[colorKey] = self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) } let _ = animationView.update( From c1595c9de9e45ffe70700af69306458441433c2d Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 21:38:41 +0200 Subject: [PATCH 095/113] Emoji improvements --- .../Sources/DefaultDayPresentationTheme.swift | 2 +- .../ChatInterfaceStateAccessoryPanels.swift | 2 +- .../Sources/ChatTextInputPanelNode.swift | 14 +- .../Sources/ForwardAccessoryPanelNode.swift | 174 ++++++++++-------- .../Sources/PeerSelectionControllerNode.swift | 2 +- 5 files changed, 112 insertions(+), 82 deletions(-) diff --git a/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift b/submodules/TelegramPresentationData/Sources/DefaultDayPresentationTheme.swift index bc6bb3a410..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), diff --git a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift index a0a8432548..7e5e257aa2 100644 --- a/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift +++ b/submodules/TelegramUI/Sources/ChatInterfaceStateAccessoryPanels.swift @@ -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 } diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 6d5a77b118..6b6a608c10 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -119,7 +119,7 @@ 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 let .input(isEnabled, inputMode), let .botInput(isEnabled, inputMode): switch inputMode { @@ -149,7 +149,7 @@ 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 .input, .botInput, .silentPost, .commands, .scheduledMessages: return 32.0 @@ -175,7 +175,9 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { self.iconImageNode.frame = imageFrame if let animationView = self.animationView { - let animationFrame = imageFrame.insetBy(dx: -4.0, dy: -4.0) + let iconSize: CGSize = CGSize(width: 32.0, height: 32.0) + let iconFrame = CGRect(origin: CGPoint(x: floor((size.width - iconSize.width) / 2.0), y: floor((size.height - iconSize.height) / 2.0) - bottomInset), size: iconSize) + let animationFrame = iconFrame.insetBy(dx: -4.0, dy: -4.0) var previousInputMode: ChatTextInputAccessoryItem.InputMode? var inputMode: ChatTextInputAccessoryItem.InputMode? @@ -274,7 +276,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { colors[colorKey] = self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) } - let _ = animationView.update( + let animationSize = animationView.update( transition: .immediate, component: AnyComponent(LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( @@ -282,7 +284,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { mode: animationMode ), colors: colors, - size: animationFrame.size + size: CGSize(width: 32.0, height: 32.0) )), environment: {}, containerSize: animationFrame.size @@ -292,7 +294,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { if view.superview == nil { self.view.addSubview(view) } - view.frame = animationFrame + 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) } } } 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/PeerSelectionControllerNode.swift b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift index ac30fa69f4..798e6d568a 100644 --- a/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift +++ b/submodules/TelegramUI/Sources/PeerSelectionControllerNode.swift @@ -386,7 +386,7 @@ 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 From b96430093c9252d29ac22e7495da733902a208bb Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Sun, 24 Jul 2022 22:57:22 +0300 Subject: [PATCH 096/113] Various fixes --- submodules/ChatSendMessageActionUI/BUILD | 1 + ...ChatSendMessageActionSheetController.swift | 6 +- ...SendMessageActionSheetControllerNode.swift | 132 +++++++++++++++++- submodules/Display/Source/GridNode.swift | 4 +- .../Display/Source/HapticFeedback.swift | 11 +- .../Items/ItemListDisclosureItem.swift | 19 ++- .../PrivacyAndSecurityController.swift | 27 ++-- .../Sources/StickerPackEmojisItem.swift | 34 ++--- .../Sources/StickerPackScreen.swift | 16 +-- .../TelegramUI/Sources/ChatController.swift | 2 +- .../Sources/ChatControllerNode.swift | 2 +- .../Sources/ChatEntityKeyboardInputNode.swift | 9 +- .../WebUI/Sources/WebAppController.swift | 67 ++++----- 13 files changed, 245 insertions(+), 85 deletions(-) diff --git a/submodules/ChatSendMessageActionUI/BUILD b/submodules/ChatSendMessageActionUI/BUILD index f031506ecc..51314b168b 100644 --- a/submodules/ChatSendMessageActionUI/BUILD +++ b/submodules/ChatSendMessageActionUI/BUILD @@ -20,6 +20,7 @@ swift_library( "//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 d191144be9..50a0b0858e 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetController.swift @@ -57,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) + } } }) @@ -93,7 +95,7 @@ public final class ChatSendMessageActionSheetController: ViewController { 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, send: { [weak self] in + 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 8d10ae6b7e..3164dcec7c 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -10,6 +10,7 @@ import AccountContext import AppBundle import ContextUI import TextFormat +import EmojiTextAttachmentView private let leftInset: CGFloat = 16.0 private let rightInset: CGFloat = 16.0 @@ -177,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 { @@ -185,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?, hasEntityKeyboard: Bool, 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 @@ -194,6 +200,7 @@ final class ChatSendMessageActionSheetControllerNode: ViewControllerTracingNode, self.attachment = attachment self.forwardedCount = forwardedCount self.hasEntityKeyboard = hasEntityKeyboard + self.emojiViewProvider = emojiViewProvider self.send = send self.cancel = cancel @@ -351,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 @@ -459,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) { @@ -692,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/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/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/ItemListUI/Sources/Items/ItemListDisclosureItem.swift b/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift index b233875508..30ba660d9b 100644 --- a/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift +++ b/submodules/ItemListUI/Sources/Items/ItemListDisclosureItem.swift @@ -20,7 +20,7 @@ public enum ItemListDisclosureLabelStyle { case text case detailText case coloredText(UIColor) -// case textWithIcon(UIColor) + case textWithIcon(UIImage) case multilineDetailText case badge(UIColor) case color(UIColor) @@ -236,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 } @@ -474,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/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift index a20f4fe1d8..95bf79323e 100644 --- a/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift +++ b/submodules/SettingsUI/Sources/Privacy and Security/PrivacyAndSecurityController.swift @@ -83,7 +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) + case voiceMessagePrivacy(PresentationTheme, String, String, Bool) case selectivePrivacyInfo(PresentationTheme, String) case passcode(PresentationTheme, String, Bool, String) case twoStepVerification(PresentationTheme, String, String, TwoStepVerificationAccessConfiguration?) @@ -209,8 +209,8 @@ private enum PrivacyAndSecurityEntry: ItemListNodeEntry { } else { return false } - case let .voiceMessagePrivacy(lhsTheme, lhsText, lhsValue): - if case let .voiceMessagePrivacy(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 @@ -300,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): @@ -323,8 +323,8 @@ 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): - return ItemListDisclosureItem(presentationData: presentationData, title: text, label: value, sectionId: self.section, style: .blocks, action: { + 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): @@ -411,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!)"))) @@ -449,7 +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))) + 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))) @@ -458,7 +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)) + 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)) @@ -944,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 @@ -959,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)) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift index 41773c8e84..b43be1d5c7 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackEmojisItem.swift @@ -103,16 +103,14 @@ final class StickerPackEmojisItem: GridItem { func node(layout: GridNodeLayout, synchronousLoad: Bool) -> GridItemNode { let node = StickerPackEmojisItemNode() - node.setup(item: self) return node } func update(node: GridItemNode) { - guard let node = node as? StickerPackEmojisItemNode else { + guard let _ = node as? StickerPackEmojisItemNode else { assertionFailure() return } - node.setup(item: self) } } @@ -173,7 +171,7 @@ final class StickerPackEmojisItemNode: GridItemNode { let shimmerHostView = PortalSourceView() shimmerHostView.alpha = 0.0 - shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.frame.size) + shimmerHostView.frame = CGRect(origin: CGPoint(), size: self.size) self.view.addSubview(shimmerHostView) self.shimmerHostView = shimmerHostView @@ -194,10 +192,14 @@ final class StickerPackEmojisItemNode: GridItemNode { } self.boundsChangeTrackerLayer = boundsChangeTrackerLayer } - - private var setupTimestamp: Double? - func setup(item: StickerPackEmojisItem) { + + 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 @@ -217,9 +219,9 @@ final class StickerPackEmojisItemNode: GridItemNode { self.setNeedsLayout() } - + func updateVisibleItems(attemptSynchronousLoads: Bool, transition: ContainedViewLayoutTransition) { - guard let item = self.item, !self.frame.width.isZero else { + guard let item = self.item, !self.size.width.isZero else { return } @@ -231,10 +233,10 @@ final class StickerPackEmojisItemNode: GridItemNode { var validIds = Set() let itemLayout: ItemLayout - if let current = self.itemLayout, current.width == self.frame.width && current.itemsCount == items.count && current.hasTitle == (item.title != nil) { + 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.frame.width, itemsCount: items.count, hasTitle: item.title != nil) + itemLayout = ItemLayout(width: self.size.width, itemsCount: items.count, hasTitle: item.title != nil) self.itemLayout = itemLayout } @@ -368,20 +370,20 @@ final class StickerPackEmojisItemNode: GridItemNode { super.layout() if let _ = self.item { - var buttonSize = self.buttonNode.calculateSizeThatFits(self.frame.size) + var buttonSize = self.buttonNode.calculateSizeThatFits(self.size) buttonSize.width += 24.0 buttonSize.height = 28.0 - let titleSize = self.titleNode.updateLayout(CGSize(width: self.frame.width - 60.0, height: self.frame.height)) - let subtitleSize = self.subtitleNode.updateLayout(CGSize(width: self.frame.width - 60.0, height: self.frame.height)) + 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.frame.width - buttonSize.width - 16.0, y: 17.0), size: buttonSize) + 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.frame.size) + self.shimmerHostView?.frame = CGRect(origin: CGPoint(), size: self.size) self.updateVisibleItems(attemptSynchronousLoads: false, transition: .immediate) } diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 1401791f68..ef35698c49 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -911,14 +911,6 @@ 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) } @@ -1050,6 +1042,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() diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 7f5f65bc9d..07e99c1e64 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -3617,7 +3617,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() } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index d9ff15c6ca..cb2dbacdf5 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -125,7 +125,7 @@ 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? diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index a55fcff8de..9a16ad296c 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -1055,7 +1055,14 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } if isPremiumLocked { - let controller = PremiumIntroScreen(context: context, source: .stickers) + 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 diff --git a/submodules/WebUI/Sources/WebAppController.swift b/submodules/WebUI/Sources/WebAppController.swift index 1e74242bed..e939b3a9d5 100644 --- a/submodules/WebUI/Sources/WebAppController.swift +++ b/submodules/WebUI/Sources/WebAppController.swift @@ -800,39 +800,40 @@ public final class WebAppController: ViewController, AttachmentContainable { self.needDismissConfirmation = needConfirmation } case "web_app_request_phone": - 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)) - }) + 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 } From 3f9f29b7fb5b4f3dbe73800b32aafa9d4b88d3f9 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 00:08:32 +0300 Subject: [PATCH 097/113] Various fixes --- .../Sources/BotCheckoutControllerNode.swift | 14 ++++++++------ .../Sources/BotCheckoutPaymentMethodSheet.swift | 8 ++++++-- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index 881b4467a4..b2cb0c4268 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -810,9 +810,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 } @@ -891,7 +891,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 } @@ -961,7 +961,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 { @@ -1060,12 +1060,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)) } } diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift index 054c97d2cf..f93c6e9fc6 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutPaymentMethodSheet.swift @@ -39,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 @@ -82,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() })) } From 2f6cf1618ccd91156d037083bbe046b7d008f199 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 23:14:47 +0200 Subject: [PATCH 098/113] Emoji improvements --- .../AttachmentTextInputPanelNode.swift | 13 +- .../Sources/EmojiPagerContentComponent.swift | 6 +- .../EntityKeyboardTopPanelComponent.swift | 4 +- .../Contents.json | 15 ++ .../trending_243.pdf | 97 ++++++++++ .../Contents.json | 2 +- .../ic_tools.pdf | 177 ------------------ .../keyboard_2444.svg | 3 + .../PanelFeaturedIcon.imageset/Contents.json | 2 +- .../PanelFeaturedIcon.imageset/Group 1.svg | 3 + .../trending_24.svg | 3 - .../PanelRecentIcon.imageset/Contents.json | 2 +- .../PanelRecentIcon.imageset/Frame 123.svg | 4 + .../PanelRecentIcon.imageset/recent_24.svg | 3 - .../PanelSavedIcon.imageset/Contents.json | 2 +- .../PanelSavedIcon.imageset/favourites_24.svg | 3 - .../favourites_2455.svg | 3 + .../PanelTrendingIcon.imageset/Contents.json | 2 +- .../trendinggifs_24.svg | 3 - .../trendinggifs_24123.svg | 4 + .../Sources/ChatControllerNode.swift | 22 ++- 21 files changed, 162 insertions(+), 211 deletions(-) create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/Contents.json create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputPremiumIcon.imageset/trending_243.pdf delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/keyboard_2444.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Group 1.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/trending_24.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Frame 123.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/recent_24.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_24.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_2455.svg delete mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24.svg create mode 100644 submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24123.svg diff --git a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift index ab164cbba7..784a68f5c3 100644 --- a/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift +++ b/submodules/AttachmentTextInputPanelNode/Sources/AttachmentTextInputPanelNode.swift @@ -908,19 +908,16 @@ public class AttachmentTextInputPanelNode: ASDisplayNode, TGCaptionPanelView, AS var colors: [String: UIColor] = [:] let colorKeys: [String] = [ - "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" + "__allcolors__" ] + let color = defaultDarkPresentationTheme.chat.inputPanel.inputControlColor for colorKey in colorKeys { - colors[colorKey] = presentationInterfaceState.theme.chat.inputPanel.inputControlColor + colors[colorKey] = color } let animationComponent = LottieAnimationComponent( animation: LottieAnimationComponent.AnimationItem( - name: "anim_smiletosticker", - mode: .animateTransitionFromPrevious + 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) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index f36990b98a..ca20687d7d 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -672,7 +672,11 @@ private final class GroupHeaderLayer: UIView { } let textFrame: CGRect - textFrame = CGRect(origin: CGPoint(x: titleHorizontalOffset + floor((constrainedSize.width - titleHorizontalOffset - textSize.width) / 2.0), y: textOffsetY), size: textSize) + 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 diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 694a8b0956..de14c724c5 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -322,9 +322,9 @@ final class EntityKeyboardIconTopPanelComponent: Component { case .saved: image = UIImage(bundleImageName: "Chat/Input/Media/PanelSavedIcon") case .premium: - image = generateImage(CGSize(width: 44.0, height: 42.0), contextGenerator: { size, context in + 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: "Peer Info/PremiumIcon") { + if let image = UIImage(bundleImageName: "Chat/Input/Media/EntityInputPremiumIcon") { if let cgImage = image.cgImage { context.clip(to: CGRect(origin: .zero, size: size), mask: cgImage) } 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/EntityInputSettingsIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json index 67a1f22d45..92f837ea2b 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "ic_tools.pdf", + "filename" : "keyboard_2444.svg", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf deleted file mode 100644 index 702905fc0c..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/EntityInputSettingsIcon.imageset/ic_tools.pdf +++ /dev/null @@ -1,177 +0,0 @@ -%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.459991 2.485321 cm -0.000000 0.000000 0.000000 scn -11.355469 0.000000 m -13.722656 0.000000 l -14.625000 0.000000 15.316406 0.550781 15.527344 1.417969 c -16.031250 3.609375 l -16.406250 3.738281 l -18.316406 2.566406 l -19.078125 2.085938 19.957031 2.203125 20.601562 2.847656 c -22.242188 4.476562 l -22.886719 5.121094 23.003906 6.011719 22.523438 6.761719 c -21.328125 8.660156 l -21.468750 9.011719 l -23.660156 9.527344 l -24.515625 9.738281 25.078125 10.441406 25.078125 11.332031 c -25.078125 13.652344 l -25.078125 14.542969 24.527344 15.246094 23.660156 15.457031 c -21.492188 15.984375 l -21.339844 16.359375 l -22.535156 18.257812 l -23.015625 19.007812 22.898438 19.886719 22.253906 20.542969 c -20.613281 22.183594 l -19.980469 22.816406 19.101562 22.933594 18.339844 22.464844 c -16.429688 21.292969 l -16.031250 21.445312 l -15.527344 23.636719 l -15.316406 24.503906 14.625000 25.054688 13.722656 25.054688 c -11.355469 25.054688 l -10.453125 25.054688 9.761719 24.503906 9.550781 23.636719 c -9.035156 21.445312 l -8.636719 21.292969 l -6.738281 22.464844 l -5.976562 22.933594 5.085938 22.816406 4.453125 22.183594 c -2.824219 20.542969 l -2.179688 19.886719 2.050781 19.007812 2.542969 18.257812 c -3.726562 16.359375 l -3.585938 15.984375 l -1.417969 15.457031 l -0.550781 15.246094 0.000000 14.542969 0.000000 13.652344 c -0.000000 11.332031 l -0.000000 10.441406 0.562500 9.738281 1.417969 9.527344 c -3.609375 9.011719 l -3.738281 8.660156 l -2.554688 6.761719 l -2.062500 6.011719 2.191406 5.121094 2.835938 4.476562 c -4.464844 2.847656 l -5.109375 2.203125 6.000000 2.085938 6.761719 2.566406 c -8.660156 3.738281 l -9.035156 3.609375 l -9.550781 1.417969 l -9.761719 0.550781 10.453125 0.000000 11.355469 0.000000 c -h -11.542969 1.828125 m -11.343750 1.828125 11.238281 1.910156 11.203125 2.097656 c -10.500000 5.003906 l -9.785156 5.179688 9.117188 5.460938 8.613281 5.777344 c -6.058594 4.207031 l -5.917969 4.101562 5.765625 4.125000 5.625000 4.265625 c -4.242188 5.648438 l -4.113281 5.777344 4.101562 5.917969 4.195312 6.082031 c -5.765625 8.613281 l -5.496094 9.105469 5.191406 9.773438 5.003906 10.488281 c -2.097656 11.179688 l -1.910156 11.214844 1.828125 11.320312 1.828125 11.519531 c -1.828125 13.476562 l -1.828125 13.687500 1.898438 13.781250 2.097656 13.816406 c -4.992188 14.519531 l -5.179688 15.281250 5.531250 15.972656 5.742188 16.406250 c -4.183594 18.937500 l -4.078125 19.113281 4.089844 19.253906 4.218750 19.394531 c -5.613281 20.753906 l -5.753906 20.894531 5.882812 20.917969 6.058594 20.812500 c -8.589844 19.277344 l -9.093750 19.558594 9.808594 19.851562 10.511719 20.050781 c -11.203125 22.957031 l -11.238281 23.144531 11.343750 23.226562 11.542969 23.226562 c -13.535156 23.226562 l -13.734375 23.226562 13.839844 23.144531 13.863281 22.957031 c -14.578125 20.027344 l -15.304688 19.839844 15.937500 19.546875 16.464844 19.265625 c -19.007812 20.812500 l -19.195312 20.917969 19.312500 20.894531 19.464844 20.753906 c -20.847656 19.394531 l -20.988281 19.253906 20.988281 19.113281 20.882812 18.937500 c -19.324219 16.406250 l -19.546875 15.972656 19.886719 15.281250 20.074219 14.519531 c -22.980469 13.816406 l -23.167969 13.781250 23.250000 13.687500 23.250000 13.476562 c -23.250000 11.519531 l -23.250000 11.320312 23.156250 11.214844 22.980469 11.179688 c -20.062500 10.488281 l -19.875000 9.773438 19.582031 9.105469 19.300781 8.613281 c -20.871094 6.082031 l -20.964844 5.917969 20.964844 5.777344 20.824219 5.648438 c -19.453125 4.265625 l -19.300781 4.125000 19.160156 4.101562 19.007812 4.207031 c -16.453125 5.777344 l -15.949219 5.460938 15.292969 5.179688 14.578125 5.003906 c -13.863281 2.097656 l -13.839844 1.910156 13.734375 1.828125 13.535156 1.828125 c -11.542969 1.828125 l -h -12.539062 8.050781 m -14.988281 8.050781 17.003906 10.066406 17.003906 12.527344 c -17.003906 14.964844 14.988281 16.980469 12.539062 16.980469 c -10.089844 16.980469 8.062500 14.964844 8.062500 12.527344 c -8.062500 10.078125 10.078125 8.050781 12.539062 8.050781 c -h -12.539062 9.867188 m -11.085938 9.867188 9.890625 11.062500 9.890625 12.527344 c -9.890625 13.968750 11.085938 15.164062 12.539062 15.164062 c -13.968750 15.164062 15.164062 13.968750 15.164062 12.527344 c -15.164062 11.074219 13.968750 9.867188 12.539062 9.867188 c -h -f -n -Q - -endstream -endobj - -3 0 obj - 4265 -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 -0000004355 00000 n -0000004378 00000 n -0000004551 00000 n -0000004625 00000 n -trailer -<< /ID [ (some) (id) ] - /Root 6 0 R - /Size 7 ->> -startxref -4684 -%%EOF \ No newline at end of file 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/PanelFeaturedIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json index 4a012887e4..5a3751c0b4 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "trending_24.svg", + "filename" : "Group 1.svg", "idiom" : "universal" } ], 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/PanelFeaturedIcon.imageset/trending_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/trending_24.svg deleted file mode 100644 index 347b33ad8b..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelFeaturedIcon.imageset/trending_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - 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 index a306f2cfb1..5d351b207e 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "recent_24.svg", + "filename" : "Frame 123.svg", "idiom" : "universal" } ], 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/PanelRecentIcon.imageset/recent_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/recent_24.svg deleted file mode 100644 index af321b3e8c..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelRecentIcon.imageset/recent_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - 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 index e8a3780f19..a16dd2f3bf 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "favourites_24.svg", + "filename" : "favourites_2455.svg", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_24.svg deleted file mode 100644 index af8623783e..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelSavedIcon.imageset/favourites_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - 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/PanelTrendingIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json index 5ae583d444..054e167a39 100644 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json +++ b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/Contents.json @@ -1,7 +1,7 @@ { "images" : [ { - "filename" : "trendinggifs_24.svg", + "filename" : "trendinggifs_24123.svg", "idiom" : "universal" } ], diff --git a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24.svg b/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24.svg deleted file mode 100644 index fddeaac987..0000000000 --- a/submodules/TelegramUI/Images.xcassets/Chat/Input/Media/PanelTrendingIcon.imageset/trendinggifs_24.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - 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/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 974e1a4719..0c203b1529 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -1403,13 +1403,19 @@ 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)) - if let inputNode = self.inputNode { - if inputNode.hideInput { - inputPanelFrame = inputPanelFrame!.offsetBy(dx: 0.0, dy: -inputPanelFrame!.height) - } - } + inputPanelFrame = inputPanelFrame!.offsetBy(dx: 0.0, dy: inputPanelHideOffset) if self.dismissedAsOverlay { inputPanelFrame!.origin.y = layout.size.height } @@ -1432,10 +1438,14 @@ 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 { From 6b83f7392eb9fbf6f7956807b7dafecd18cf7619 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 23:17:40 +0200 Subject: [PATCH 099/113] Temp --- submodules/ChatSendMessageActionUI/BUILD | 1 + .../Sources/ChatSendMessageActionSheetControllerNode.swift | 1 + 2 files changed, 2 insertions(+) diff --git a/submodules/ChatSendMessageActionUI/BUILD b/submodules/ChatSendMessageActionUI/BUILD index f031506ecc..02c6de9261 100644 --- a/submodules/ChatSendMessageActionUI/BUILD +++ b/submodules/ChatSendMessageActionUI/BUILD @@ -20,6 +20,7 @@ swift_library( "//submodules/ContextUI:ContextUI", "//submodules/AppBundle:AppBundle", "//submodules/TextFormat:TextFormat", + "//submodules/TelegramUI/Components/TextNodeWithEntities:TextNodeWithEntities", ], visibility = [ "//visibility:public", diff --git a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift index 8d10ae6b7e..6ab48d4b4b 100644 --- a/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift +++ b/submodules/ChatSendMessageActionUI/Sources/ChatSendMessageActionSheetControllerNode.swift @@ -10,6 +10,7 @@ import AccountContext import AppBundle import ContextUI import TextFormat +import TextNodeWithEntities private let leftInset: CGFloat = 16.0 private let rightInset: CGFloat = 16.0 From ccdd8efc6ec29f945a6fa372b2f52cae20f0fcdd Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 24 Jul 2022 23:27:31 +0200 Subject: [PATCH 100/113] Emoji improvements --- .../EntityKeyboardTopPanelComponent.swift | 5 +- .../TelegramUI/Sources/ChatController.swift | 4 +- .../Sources/ChatEntityKeyboardInputNode.swift | 115 ++++++++++-------- 3 files changed, 66 insertions(+), 58 deletions(-) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index de14c724c5..7b95bf7d1f 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -515,6 +515,7 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { 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) @@ -682,7 +683,7 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { 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, 126.0), height: availableSize.height)) + 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 @@ -1902,7 +1903,7 @@ final class EntityKeyboardTopPanelComponent: Component { if itemLayout.isExpanded { expandedInset = -2.0 } else { - expandedInset = -itemLayout.sideInset - (itemFrame.width + itemLayout.itemSpacing) * 2.0 + expandedInset = -itemLayout.sideInset - (itemLayout.itemSize.width + itemLayout.itemSpacing) * 2.0 } self.scrollView.scrollRectToVisible(itemFrame.insetBy(dx: expandedInset, dy: 0.0), animated: true) break diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index a396a9928b..98b49ee5fa 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -10940,7 +10940,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return nil } - return EntityInputView(context: strongSelf.context, isDark: true) + return EntityInputView(context: strongSelf.context, isDark: true, isSecret: strongSelf.chatLocation.peerId?.namespace == Namespaces.Peer.SecretChat) }) inputPanelNode.interfaceInteraction = interfaceInteraction inputPanelNode.effectivePresentationInterfaceState = { @@ -11180,7 +11180,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G guard let strongSelf = self else { return nil } - return EntityInputView(context: strongSelf.context, isDark: false) + 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 { diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index a427216356..771955d1e6 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -86,7 +86,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { } } - static func emojiInputData(context: AccountContext, animationCache: AnimationCache, animationRenderer: MultiAnimationRenderer, isStandalone: Bool) -> Signal { + 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 { @@ -135,6 +135,10 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { continue } + if isSecret, case .file = item.content { + continue + } + let resultItem: EmojiPagerContentComponent.Item switch item.content { case let .file(file): @@ -186,62 +190,64 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { installedCollectionIds.insert(id) } - 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) { + 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 + ) - for item in featuredEmojiPack.topItems { - 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 - let supergroupId = featuredEmojiPack.info.id - let groupId: AnyHashable = supergroupId - let isPremiumLocked: Bool = item.file.isPremiumEmoji && !hasPremium - if isPremiumLocked && isPremiumDisabled { + 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 } - 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])) + + 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])) + } } } } @@ -303,7 +309,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { animationRenderer = MultiAnimationRendererImpl() //} - let emojiItems = emojiInputData(context: context, animationCache: animationCache, animationRenderer: animationRenderer, isStandalone: false) + 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] @@ -1925,7 +1931,8 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV init( context: AccountContext, - isDark: Bool + isDark: Bool, + isSecret: Bool ) { self.context = context @@ -2039,7 +2046,7 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV let semaphore = DispatchSemaphore(value: 0) var emojiComponent: EmojiPagerContentComponent? - let _ = ChatEntityKeyboardInputNode.emojiInputData(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, isStandalone: true).start(next: { value in + let _ = ChatEntityKeyboardInputNode.emojiInputData(context: context, animationCache: self.animationCache, animationRenderer: self.animationRenderer, isStandalone: true, isSecret: isSecret).start(next: { value in emojiComponent = value semaphore.signal() }) From 985c662ada90c9a265b51e226a12566edb0b10ec Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 25 Jul 2022 00:34:14 +0200 Subject: [PATCH 101/113] Add missing localization --- .../Telegram-iOS/en.lproj/Localizable.strings | 16 +++++++ .../InstalledStickerPacksController.swift | 6 +-- .../Sources/MessageContentKind.swift | 43 ++++++++++++++++++- .../Sources/EmojiPagerContentComponent.swift | 31 +++++++------ .../Sources/EntityKeyboard.swift | 39 +++++++++-------- .../TelegramUI/Sources/ChatController.swift | 5 +-- .../Sources/ChatControllerNode.swift | 5 +-- .../Sources/ChatEntityKeyboardInputNode.swift | 26 +++++------ 8 files changed, 110 insertions(+), 61 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index f208f82f9f..4548ef4b0b 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7910,3 +7910,19 @@ Sorry for the inconvenience."; "StickerPack.EmojiCount_any" = "%@ emoji"; "StickerSettings.EmojiContextInfo" = "If you archive an emoji set, you can quickly restore it later from the Archived Emoji section."; + +"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/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index 1d78a0fb79..f24eedbc3a 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -568,8 +568,7 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati } entries.append(.masks(presentationData.theme, presentationData.strings.MaskStickerSettings_Title)) - //TODO:localize - entries.append(.emoji(presentationData.theme, "Emoji")) + entries.append(.emoji(presentationData.theme, presentationData.strings.StickersList_EmojiItem)) entries.append(.quickReaction(presentationData.strings.Settings_QuickReactionSetup_NavigationTitle, quickReactionImage)) @@ -614,8 +613,7 @@ private func installedStickerPacksControllerEntries(presentationData: Presentati } case .emoji: if let archived = archived, !archived.isEmpty { - //TODO:localize - entries.append(.archived(presentationData.theme, "Archived Emoji", Int32(archived.count), archived)) + entries.append(.archived(presentationData.theme, presentationData.strings.StickersList_ArchivedEmojiItem, Int32(archived.count), archived)) } } diff --git a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift index dcaf7fa6ce..74664be74d 100644 --- a/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift +++ b/submodules/TelegramStringFormatting/Sources/MessageContentKind.swift @@ -300,8 +300,47 @@ public func foldLineBreaks(_ text: String) -> String { } public func foldLineBreaks(_ text: NSAttributedString) -> NSAttributedString { - //TODO:localize - return text + 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 { diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index ca20687d7d..a9c2181733 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -2144,7 +2144,7 @@ public final class EmojiPagerContentComponent: Component { private var component: EmojiPagerContentComponent? private weak var state: EmptyComponentState? private var pagerEnvironment: PagerComponentChildEnvironment? - private var theme: PresentationTheme? + private var keyboardChildEnvironment: EntityKeyboardChildEnvironment? private var activeItemUpdated: ActionSlot<(AnyHashable, AnyHashable?, Transition)>? private var itemLayout: ItemLayout? @@ -3010,7 +3010,7 @@ public final class EmojiPagerContentComponent: Component { } 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 theme = self.theme, let itemLayout = self.itemLayout else { + guard let component = self.component, let pagerEnvironment = self.pagerEnvironment, let keyboardChildEnvironment = self.keyboardChildEnvironment, let itemLayout = self.itemLayout else { return } @@ -3089,7 +3089,7 @@ public final class EmojiPagerContentComponent: Component { let (groupHeaderSize, centralContentWidth) = groupHeaderView.update( context: component.context, - theme: theme, + theme: keyboardChildEnvironment.theme, layoutType: itemLayout.layoutType, hasTopSeparator: hasTopSeparator, actionButtonTitle: actionButtonTitle, @@ -3130,7 +3130,7 @@ public final class EmojiPagerContentComponent: Component { self.scrollView.layer.insertSublayer(groupBorderLayer, at: 0) self.mirrorContentScrollView.layer.addSublayer(groupBorderLayer.tintContainerLayer) - groupBorderLayer.strokeColor = theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor + groupBorderLayer.strokeColor = keyboardChildEnvironment.theme.chat.inputMediaPanel.panelContentVibrantOverlayColor.cgColor groupBorderLayer.tintContainerLayer.strokeColor = UIColor.white.cgColor groupBorderLayer.lineWidth = 1.6 groupBorderLayer.lineCap = .round @@ -3198,7 +3198,6 @@ public final class EmojiPagerContentComponent: Component { let groupId = itemGroup.groupId let isPremiumLocked = itemGroup.isPremiumLocked - //TODO:localize let title: String let backgroundColor: UIColor let backgroundColors: [UIColor] @@ -3206,7 +3205,7 @@ public final class EmojiPagerContentComponent: Component { let animationName: String? let gloss: Bool if itemGroup.isPremiumLocked { - title = "Unlock \(itemGroup.title ?? "Emoji")" + title = keyboardChildEnvironment.strings.EmojiInput_UnlockPack(itemGroup.title ?? "Emoji").string backgroundColors = [ UIColor(rgb: 0x0077ff), UIColor(rgb: 0x6b93ff), @@ -3218,10 +3217,10 @@ public final class EmojiPagerContentComponent: Component { animationName = "premium_unlock" gloss = true } else { - title = "Add \(itemGroup.title ?? "Emoji")" + title = keyboardChildEnvironment.strings.EmojiInput_AddPack(itemGroup.title ?? "Emoji").string backgroundColors = [] - backgroundColor = theme.list.itemCheckColors.fillColor - foregroundColor = theme.list.itemCheckColors.foregroundColor + backgroundColor = keyboardChildEnvironment.theme.list.itemCheckColors.fillColor + foregroundColor = keyboardChildEnvironment.theme.list.itemCheckColors.foregroundColor animationName = nil gloss = false } @@ -3291,7 +3290,7 @@ public final class EmojiPagerContentComponent: Component { } let baseItemFrame = itemLayout.frame(groupIndex: groupItems.groupIndex, itemIndex: collapsedItemIndex) - let buttonSize = groupExpandActionButton.update(theme: theme, title: collapsedItemText) + 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) } @@ -3338,8 +3337,8 @@ public final class EmojiPagerContentComponent: Component { staticEmoji: item.staticEmoji, cache: component.animationCache, renderer: component.animationRenderer, - placeholderColor: theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), - blurredBadgeColor: theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), + placeholderColor: keyboardChildEnvironment.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), + 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 { @@ -3421,7 +3420,7 @@ public final class EmojiPagerContentComponent: Component { 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: theme.list.plainBackgroundColor) + 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 { @@ -3566,7 +3565,7 @@ public final class EmojiPagerContentComponent: Component { } public func pagerUpdateBackground(backgroundFrame: CGRect, transition: Transition) { - guard let theme = self.theme else { + guard let keyboardChildEnvironment = self.keyboardChildEnvironment else { return } @@ -3584,7 +3583,7 @@ public final class EmojiPagerContentComponent: Component { vibrancyEffectView.contentView.addSubview(self.mirrorContentScrollView) } - self.backgroundView.updateColor(color: theme.chat.inputMediaPanel.backgroundColor, enableBlur: true, forceKeepBlur: false, transition: transition.containedViewLayoutTransition) + 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) @@ -3604,7 +3603,7 @@ public final class EmojiPagerContentComponent: Component { let keyboardChildEnvironment = environment[EntityKeyboardChildEnvironment.self].value let pagerEnvironment = environment[PagerComponentChildEnvironment.self].value - self.theme = keyboardChildEnvironment.theme + self.keyboardChildEnvironment = keyboardChildEnvironment self.activeItemUpdated = keyboardChildEnvironment.getContentActiveItemUpdated(component.id) self.pagerEnvironment = pagerEnvironment diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift index 738ed544e1..b3423d2bbc 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboard.swift @@ -13,13 +13,16 @@ 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 } @@ -27,6 +30,9 @@ public final class EntityKeyboardChildEnvironment: Equatable { if lhs.theme !== rhs.theme { return false } + if lhs.strings !== rhs.strings { + return false + } return true } @@ -74,6 +80,7 @@ public final class EntityKeyboardComponent: Component { } public let theme: PresentationTheme + public let strings: PresentationStrings public let containerInsets: UIEdgeInsets public let emojiContent: EmojiPagerContentComponent public let stickerContent: EmojiPagerContentComponent? @@ -93,6 +100,7 @@ public final class EntityKeyboardComponent: Component { public init( theme: PresentationTheme, + strings: PresentationStrings, containerInsets: UIEdgeInsets, emojiContent: EmojiPagerContentComponent, stickerContent: EmojiPagerContentComponent?, @@ -111,6 +119,7 @@ public final class EntityKeyboardComponent: Component { isExpanded: Bool ) { self.theme = theme + self.strings = strings self.containerInsets = containerInsets self.emojiContent = emojiContent self.stickerContent = stickerContent @@ -133,6 +142,9 @@ public final class EntityKeyboardComponent: Component { if lhs.theme !== rhs.theme { return false } + if lhs.strings !== rhs.strings { + return false + } if lhs.containerInsets != rhs.containerInsets { return false } @@ -227,7 +239,6 @@ public final class EntityKeyboardComponent: Component { if let gifContent = component.gifContent { contents.append(AnyComponentWithIdentity(id: "gifs", component: AnyComponent(gifContent))) var topGifItems: [EntityKeyboardTopPanelComponent.Item] = [] - //TODO:localize if component.hasRecentGifs { topGifItems.append(EntityKeyboardTopPanelComponent.Item( id: "recent", @@ -235,7 +246,7 @@ public final class EntityKeyboardComponent: Component { content: AnyComponent(EntityKeyboardIconTopPanelComponent( icon: .recent, theme: component.theme, - title: "Recent", + title: component.strings.Stickers_Recent, pressed: { [weak self] in self?.component?.switchToGifSubject(.recent) } @@ -248,7 +259,7 @@ public final class EntityKeyboardComponent: Component { content: AnyComponent(EntityKeyboardIconTopPanelComponent( icon: .trending, theme: component.theme, - title: "Trending", + title: component.strings.Stickers_Trending, pressed: { [weak self] in self?.component?.switchToGifSubject(.trending) } @@ -307,14 +318,13 @@ public final class EntityKeyboardComponent: Component { if let stickerContent = component.stickerContent { var topStickerItems: [EntityKeyboardTopPanelComponent.Item] = [] - //TODO:localize topStickerItems.append(EntityKeyboardTopPanelComponent.Item( id: "featuredTop", isReorderable: false, content: AnyComponent(EntityKeyboardIconTopPanelComponent( icon: .featured, theme: component.theme, - title: "Featured", + title: component.strings.Stickers_Trending, pressed: { [weak self] in self?.component?.stickerContent?.inputInteractionHolder.inputInteraction?.openFeatured() } @@ -328,11 +338,10 @@ public final class EntityKeyboardComponent: Component { "recent": .recent, "premium": .premium ] - //TODO:localize let titleMapping: [String: String] = [ - "saved": "Saved", - "recent": "Recent", - "premium": "Premium" + "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( @@ -419,9 +428,8 @@ public final class EntityKeyboardComponent: Component { let iconMapping: [String: EntityKeyboardIconTopPanelComponent.Icon] = [ "recent": .recent, ] - //TODO:localize let titleMapping: [String: String] = [ - "recent": "Recent", + "recent": component.strings.Stickers_Recent, ] if let icon = iconMapping[id], let title = titleMapping[id] { topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( @@ -438,13 +446,12 @@ public final class EntityKeyboardComponent: Component { )) } } else if id == "static" { - //TODO:localize topEmojiItems.append(EntityKeyboardTopPanelComponent.Item( id: itemGroup.supergroupId, isReorderable: false, content: AnyComponent(EntityKeyboardStaticStickersPanelComponent( theme: component.theme, - title: "Emoji", + title: component.strings.EmojiInput_PanelTitleEmoji, pressed: { [weak self] subgroupId in guard let strongSelf = self else { return @@ -538,10 +545,7 @@ public final class EntityKeyboardComponent: Component { contentAccessoryLeftButtons: contentAccessoryLeftButtons, contentAccessoryRightButtons: contentAccessoryRightButtons, defaultId: component.defaultToEmojiTab ? "emoji" : "stickers", - contentBackground: nil/*AnyComponent(BlurredBackgroundComponent( - color: component.theme.chat.inputMediaPanel.stickersBackgroundColor.withMultipliedAlpha(0.75), - tintContainerView: self.tintContainerView - ))*/, + contentBackground: nil, topPanel: AnyComponent(EntityKeyboardTopContainerPanelComponent( theme: component.theme, overflowHeight: component.hiddenInputHeight, @@ -573,6 +577,7 @@ public final class EntityKeyboardComponent: Component { environment: { EntityKeyboardChildEnvironment( theme: component.theme, + strings: component.strings, getContentActiveItemUpdated: { id in if id == AnyHashable("gifs") { return gifsContentItemIdUpdated diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 4a09a6553a..4c3b18a57b 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -7123,9 +7123,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G }) if let firstLockedPremiumEmoji = firstLockedPremiumEmoji { - //let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } - //TODO:localize - strongSelf.controllerInteraction?.displayUndo(.sticker(context: strongSelf.context, file: firstLockedPremiumEmoji, title: nil, text: "Subscribe to Telegram Premium to unlock premium emoji.", undoText: "More", customAction: { + 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 } diff --git a/submodules/TelegramUI/Sources/ChatControllerNode.swift b/submodules/TelegramUI/Sources/ChatControllerNode.swift index 3534b73875..09fd9c55ea 100644 --- a/submodules/TelegramUI/Sources/ChatControllerNode.swift +++ b/submodules/TelegramUI/Sources/ChatControllerNode.swift @@ -2895,9 +2895,8 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate { }) if let firstLockedPremiumEmoji = firstLockedPremiumEmoji { - //let presentationData = self.context.sharedContext.currentPresentationData.with { $0 } - //TODO:localize - self.controllerInteraction.displayUndo(.sticker(context: context, file: firstLockedPremiumEmoji, title: nil, text: "Subscribe to Telegram Premium to unlock premium emoji.", undoText: "More", customAction: { [weak self] in + 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 } diff --git a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift index ead582706d..9f068eee88 100644 --- a/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift +++ b/submodules/TelegramUI/Sources/ChatEntityKeyboardInputNode.swift @@ -99,6 +99,8 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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, @@ -160,8 +162,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Stickers_FrequentlyUsed, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) } } } @@ -179,8 +180,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Emoji", subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleEmoji, subtitle: nil, isPremiumLocked: false, isFeatured: false, isExpandable: false, items: [resultItem])) } } } @@ -418,8 +418,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Saved", subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitleFavoriteStickers, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } @@ -444,8 +443,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Recently Used", subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.Stickers_FrequentlyUsed, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } @@ -489,8 +487,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { itemGroups[groupIndex].items.append(resultItem) } else { itemGroupIndexById[groupId] = itemGroups.count - //TODO:localize - itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: "Premium", subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) + itemGroups.append(ItemGroup(supergroupId: groupId, id: groupId, title: strings.EmojiInput_SectionTitlePremiumStickers, subtitle: nil, actionButtonTitle: nil, isPremiumLocked: false, isFeatured: false, displayPremiumBadges: false, items: [resultItem])) } } } @@ -1014,11 +1011,9 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { strongSelf.currentUndoOverlayController = nil animateInAsReplacement = true } - - //TODO:localize let presentationData = context.sharedContext.currentPresentationData.with { $0 } - let controller = UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { [weak controllerInteraction] in + 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 } @@ -1545,6 +1540,7 @@ final class ChatEntityKeyboardInputNode: ChatInputNode { 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, @@ -1993,10 +1989,8 @@ final class EntityInputView: UIView, AttachmentTextInputPanelInputView, UIInputV } if file.isPremiumEmoji && !hasPremium { - //TODO:localize - let presentationData = context.sharedContext.currentPresentationData.with { $0 } - strongSelf.presentController?(UndoOverlayController(presentationData: presentationData, content: .sticker(context: context, file: file, title: nil, text: "Subscribe to Telegram Premium to unlock this emoji.", undoText: "More", customAction: { + 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 } From 5d819d8da5b2cd2ad2862800a526ad97edd74776 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 02:15:35 +0300 Subject: [PATCH 102/113] Update API --- .../Sources/BotCheckoutControllerNode.swift | 6 ++++-- submodules/TelegramApi/Sources/Api0.swift | 2 +- submodules/TelegramApi/Sources/Api26.swift | 16 ++++++++++------ .../TelegramEngine/Payments/BotPaymentForm.swift | 11 +++++------ 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift index b2cb0c4268..f4c5b8f379 100644 --- a/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift +++ b/submodules/BotPaymentsUI/Sources/BotCheckoutControllerNode.swift @@ -481,11 +481,13 @@ private func availablePaymentMethods(form: BotPaymentForm, current: BotCheckoutP methods.append(.applePay) hasApplePay = true } - if let savedCredentials = form.savedCredentials { + + 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) }) } @@ -1106,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 diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index daf94bbb99..1adb4032bc 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -1006,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[1288001087] = { 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) } diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index 2d4247b260..1845664eae 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -728,13 +728,13 @@ public extension Api.payments { } 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]) + 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(1288001087) + buffer.appendInt32(-1610250415) } serializeInt32(flags, buffer: buffer, boxed: false) serializeInt64(formId, buffer: buffer, boxed: false) @@ -753,7 +753,11 @@ public extension Api.payments { item.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)} + 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 { @@ -807,9 +811,9 @@ public extension Api.payments { 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 signature = reader.readInt32() { - _14 = Api.parse(reader, signature: signature) as? Api.PaymentSavedCredentials + 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() { diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift index 68acf4a4eb..da5c02c6d6 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Payments/BotPaymentForm.swift @@ -119,7 +119,7 @@ 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] } @@ -304,14 +304,13 @@ 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) } - } - + }) ?? [] + 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) } From 38cea1821f1cd6ac10466dcc201e2eabb7e58bde Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 02:15:50 +0300 Subject: [PATCH 103/113] Various fixes --- Telegram/Telegram-iOS/en.lproj/Localizable.strings | 3 +++ .../StickerPackPreviewUI/Sources/StickerPackScreen.swift | 7 +++++-- submodules/TelegramUI/Sources/ChatController.swift | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index f208f82f9f..10bade670d 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7910,3 +7910,6 @@ Sorry for the inconvenience."; "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"; diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index ef35698c49..0e266423e0 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -586,7 +586,10 @@ 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) @@ -595,7 +598,7 @@ private final class StickerPackContainer: ASDisplayNode { 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)) } }))) diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index 8c5e7ef83e..a50abe0a4b 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1093,7 +1093,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G var disableTransitionAnimations = false var actionsSignal: Signal = .single(actions) - if actions.tip == nil, let entitiesAttribute = message.textEntitiesAttribute { + if let entitiesAttribute = message.textEntitiesAttribute { var emojiFileIds: [Int64] = [] for entity in entitiesAttribute.entities { if case let .CustomEmoji(_, fileId) = entity.type { From 42d748ce4dfde488eb15ca4422538970770100cc Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 25 Jul 2022 01:20:57 +0200 Subject: [PATCH 104/113] Emoji fixes --- .../Sources/EmojiPagerContentComponent.swift | 18 +++++++++++------- .../EntityKeyboardTopPanelComponent.swift | 15 +++++++++------ .../ChatMessageAnimatedStickerItemNode.swift | 2 ++ .../ChatMessageInstantVideoItemNode.swift | 1 + .../Sources/ChatMessageStickerItemNode.swift | 19 +++++++++++++++++++ .../Sources/ChatTextInputPanelNode.swift | 2 +- 6 files changed, 43 insertions(+), 14 deletions(-) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index a9c2181733..3a9ddba34e 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -1717,35 +1717,38 @@ public final class EmojiPagerContentComponent: Component { 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?, + color: UIColor, size: CGSize ) { self.shimmerView = shimmerView - self.placeholderView = PortalView() self.placeholderMaskLayer = SimpleLayer() super.init(frame: CGRect()) - if let placeholderView = self.placeholderView, let shimmerView = self.shimmerView { + 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: color ?? .black) { + 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 let _ = color { + if useDirectContent { strongSelf.layer.contents = image.cgImage } else { strongSelf.placeholderMaskLayer.contents = image.cgImage @@ -3329,6 +3332,7 @@ public final class EmojiPagerContentComponent: Component { itemTransition = .immediate animateItemIn = !transition.animation.isImmediate + let placeholderColor = keyboardChildEnvironment.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1) itemLayer = ItemLayer( item: item, context: component.context, @@ -3337,7 +3341,7 @@ public final class EmojiPagerContentComponent: Component { staticEmoji: item.staticEmoji, cache: component.animationCache, renderer: component.animationRenderer, - placeholderColor: keyboardChildEnvironment.theme.chat.inputPanel.primaryTextColor.withMultipliedAlpha(0.1), + placeholderColor: placeholderColor, blurredBadgeColor: keyboardChildEnvironment.theme.chat.inputPanel.panelBackgroundColor.withMultipliedAlpha(0.5), pointSize: item.staticEmoji == nil ? itemPlaybackSize : itemVisibleFitSize, onUpdateDisplayPlaceholder: { [weak self] displayPlaceholder, duration in @@ -3354,7 +3358,7 @@ public final class EmojiPagerContentComponent: Component { context: component.context, file: file, shimmerView: strongSelf.shimmerHostView, - color: nil, + color: placeholderColor, size: itemNativeFitSize ) strongSelf.visibleItemPlaceholderViews[itemId] = placeholderView diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 7b95bf7d1f..934c2bafd0 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -138,9 +138,9 @@ final class EntityKeyboardAnimationTopPanelComponent: Component { } } - let iconFitSize: CGSize = itemEnvironment.isExpanded ? CGSize(width: 44.0, height: 44.0) : CGSize(width: 26.0, height: 26.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) + 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)) @@ -464,7 +464,7 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { self.isExpanded = isExpanded self.isActive = isActive self.baseItemSize = 42.0 - self.itemSize = isExpanded ? self.baseItemSize : 24.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 @@ -608,13 +608,16 @@ final class EntityKeyboardStaticStickersPanelComponent: Component { animationName = "emojicat_flags" } - let color: UIColor + let baseColor: UIColor if itemEnvironment.highlightedSubgroupId == AnyHashable(items[i].rawValue) { - color = component.theme.chat.inputMediaPanel.panelHighlightedIconColor + baseColor = component.theme.chat.inputMediaPanel.panelHighlightedIconColor } else { - color = component.theme.chat.inputMediaPanel.panelIconColor + 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, diff --git a/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageAnimatedStickerItemNode.swift index 513996dde0..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 } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageInstantVideoItemNode.swift index b9e933d3f8..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 } } } diff --git a/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageStickerItemNode.swift index 1b79c9be75..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() diff --git a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift index 7b23cb2613..f4a504d8eb 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputPanelNode.swift @@ -290,7 +290,7 @@ private final class AccessoryItemIconButtonNode: HighlightTrackingButtonNode { var colors: [String: UIColor] = [:] for colorKey in colorKeys { - colors[colorKey] = self.theme.chat.inputPanel.inputControlColor + colors[colorKey] = self.theme.chat.inputPanel.inputControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) } let animationSize = animationView.update( From 75f68cc6fee0ed4394bb3a56d46f1529aa1c5410 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 25 Jul 2022 02:27:31 +0200 Subject: [PATCH 105/113] Fix layout --- .../Sources/EntityKeyboardTopPanelComponent.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift index 934c2bafd0..1c4f0fe10e 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EntityKeyboardTopPanelComponent.swift @@ -1090,7 +1090,7 @@ final class EntityKeyboardTopPanelComponent: Component { 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: 126.0, height: 28.0) + 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 From f8801df14372a4a5e7142cb37305ceb4bc36dddb Mon Sep 17 00:00:00 2001 From: Ali <> Date: Mon, 25 Jul 2022 02:32:41 +0200 Subject: [PATCH 106/113] Fix animation --- .../Sources/EmojiPagerContentComponent.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift index 3a9ddba34e..4cc3c0d4fa 100644 --- a/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift +++ b/submodules/TelegramUI/Components/EntityKeyboard/Sources/EmojiPagerContentComponent.swift @@ -3404,7 +3404,7 @@ public final class EmojiPagerContentComponent: Component { itemTransition.setBounds(layer: itemLayer, bounds: CGRect(origin: CGPoint(), size: itemFrame.size)) if animateItemIn, !transition.animation.isImmediate { - if let previousItemPosition = previousItemPositions?[itemId], transitionHintInstalledGroupId != itemId.groupId { + if let previousItemPosition = previousItemPositions?[itemId], transitionHintInstalledGroupId != itemId.groupId, transitionHintExpandedGroupId != itemId.groupId { itemTransition = transition itemLayer.position = previousItemPosition } else { @@ -3437,6 +3437,11 @@ public final class EmojiPagerContentComponent: Component { } } + 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 } } From 73a84310951dba6a60deb0323d4ae48ab474a4b5 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 04:09:33 +0300 Subject: [PATCH 107/113] Various fixes --- Telegram/Telegram-iOS/Resources/Gift1.tgs | Bin 53808 -> 0 bytes Telegram/Telegram-iOS/Resources/Gift12.tgs | Bin 0 -> 60272 bytes Telegram/Telegram-iOS/Resources/Gift2.tgs | Bin 53946 -> 0 bytes Telegram/Telegram-iOS/Resources/Gift3.tgs | Bin 54100 -> 60325 bytes Telegram/Telegram-iOS/Resources/Gift6.tgs | Bin 0 -> 60192 bytes .../Items/UniversalVideoGalleryItem.swift | 20 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 183 ++++++++++-------- .../Sources/StickerPackScreen.swift | 2 +- .../Sources/ChatMessageGiftItemNode.swift | 4 +- 9 files changed, 120 insertions(+), 89 deletions(-) delete mode 100644 Telegram/Telegram-iOS/Resources/Gift1.tgs create mode 100644 Telegram/Telegram-iOS/Resources/Gift12.tgs delete mode 100644 Telegram/Telegram-iOS/Resources/Gift2.tgs create mode 100644 Telegram/Telegram-iOS/Resources/Gift6.tgs diff --git a/Telegram/Telegram-iOS/Resources/Gift1.tgs b/Telegram/Telegram-iOS/Resources/Gift1.tgs deleted file mode 100644 index f0b6f7a3cb65ff72f3ffa346b15a77aacb43d5a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 53808 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 N{(sqI(4N)r1OV0nlJ5Wj diff --git a/Telegram/Telegram-iOS/Resources/Gift12.tgs b/Telegram/Telegram-iOS/Resources/Gift12.tgs new file mode 100644 index 0000000000000000000000000000000000000000..3fb5c079072917ee1d84bd5b349c9e1a78d28ee8 GIT binary patch literal 60272 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

U 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 diff --git a/Telegram/Telegram-iOS/Resources/Gift3.tgs b/Telegram/Telegram-iOS/Resources/Gift3.tgs index ba9a105858a44bf2082107022e5db7d6fdb1bbcf..42bfb3cbcddd6c8ef3d095a82548cdb23d9b229f 100644 GIT binary patch literal 60325 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℘p3 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 e$jn{5P4|u-G~2N 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

hi{{N7ZKQfX{r9_*w3uao93x0H;mH|u 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А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 diff --git a/Telegram/Telegram-iOS/Resources/Gift6.tgs b/Telegram/Telegram-iOS/Resources/Gift6.tgs new file mode 100644 index 0000000000000000000000000000000000000000..be7a5873547837c9a95d6cc8b732301065c45be0 GIT binary patch literal 60192 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 BV%q=! literal 0 HcmV?d00001 diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 8fa355bb15..d586315cdc 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -2476,16 +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 #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 { diff --git a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index 1a8ebf6a09..c85674f73b 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -145,7 +145,7 @@ private final class ProductGroupComponent: Component { buttonView?.backgroundColor = component.selectionColor } else { UIView.animate(withDuration: 0.3, animations: { - buttonView?.backgroundColor = nil + buttonView?.backgroundColor = component.backgroundColor }) } } @@ -299,31 +299,44 @@ private final class GiftComponent: CombinedComponent { transition: context.transition ) - 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 - ) + 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 ), - maximumNumberOfLines: 1 - ), - availableSize: context.availableSize, - transition: context.transition - ) + availableSize: context.availableSize, + transition: context.transition + ) + + discountSize = CGSize(width: discount.size.width + 6.0, height: 18.0) - let 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 - ) + 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( @@ -359,17 +372,9 @@ private final class GiftComponent: CombinedComponent { context.add(title .position(CGPoint(x: insets.left + title.size.width / 2.0, y: insets.top + title.size.height / 2.0)) ) - - 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)) - ) - + context.add(subtitle - .position(CGPoint(x: insets.left + discountSize.width + 7.0 + subtitle.size.width / 2.0, y: insets.top + title.size.height + spacing + discountSize.height / 2.0)) + .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) @@ -510,13 +515,13 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { let context: AccountContext let peer: EnginePeer? - let products: [InAppPurchaseManager.Product]? + let products: [PremiumGiftProduct]? let selectedProductId: String? let present: (ViewController) -> Void let selectProduct: (String) -> Void - init(context: AccountContext, peer: EnginePeer?, products: [InAppPurchaseManager.Product]?, selectedProductId: String?, present: @escaping (ViewController) -> Void, selectProduct: @escaping (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 @@ -629,27 +634,27 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { 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 monthsCount: Int 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 - switch product.id { - case "org.telegram.telegramPremium.twelveMonths": - giftTitle = strings.Premium_Gift_Years(1) - monthsCount = 12 - discount = "-15%" - case "org.telegram.telegramPremium.sixMonths": - giftTitle = strings.Premium_Gift_Months(6) - monthsCount = 6 - discount = "-10%" - case "org.telegram.telegramPremium.threeMonths": - giftTitle = strings.Premium_Gift_Months(3) - monthsCount = 3 - discount = "-7%" - default: - giftTitle = "" - monthsCount = 1 - discount = "" + if discountValue > 0 { + discount = "-\(discountValue)%" + } else { + discount = "" } items.append(ProductGroupComponent.Item( @@ -659,7 +664,7 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { GiftComponent( title: giftTitle, totalPrice: product.price, - perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth(monthsCount)).string, + perMonthPrice: strings.Premium_Gift_PricePerMonth(product.pricePerMonth).string, discount: discount, selected: product.id == component.selectedProductId, primaryTextColor: textColor, @@ -705,19 +710,42 @@ private final class PremiumGiftScreenContentComponent: CombinedComponent { } } +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, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, push: @escaping (ViewController) -> Void, completion: @escaping (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 @@ -731,12 +759,16 @@ private final class PremiumGiftScreenComponent: CombinedComponent { 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 @@ -749,16 +781,17 @@ private final class PremiumGiftScreenComponent: CombinedComponent { var inProgress = false var peer: EnginePeer? - var products: [InAppPurchaseManager.Product]? + var products: [PremiumGiftProduct]? var selectedProductId: String? private var disposable: Disposable? private var paymentDisposable = MetaDisposable() private var activationDisposable = MetaDisposable() - init(context: AccountContext, peerId: PeerId, updateInProgress: @escaping (Bool) -> Void, present: @escaping (ViewController) -> Void, completion: @escaping (Int32) -> Void) { + 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 @@ -778,7 +811,15 @@ private final class PremiumGiftScreenComponent: CombinedComponent { context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId)) ).start(next: { [weak self] products, peer in if let strongSelf = self { - strongSelf.products = products.filter { !$0.isSubscription }.sorted(by: { $0.priceValue.compare($1.priceValue) == .orderedDescending }) + + 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 strongSelf.selectedProductId = strongSelf.products?.first?.id strongSelf.peer = peer strongSelf.updated(transition: .immediate) @@ -805,19 +846,8 @@ private final class PremiumGiftScreenComponent: CombinedComponent { guard let product = self.products?.first(where: { $0.id == self.selectedProductId }) else { return } - let (currency, amount) = product.priceCurrencyAndAmount - - let duration: Int32 - switch product.id { - case "org.telegram.telegramPremium.twelveMonths": - duration = 12 - case "org.telegram.telegramPremium.sixMonths": - duration = 6 - case "org.telegram.telegramPremium.threeMonths": - duration = 3 - default: - duration = 0 - } + let (currency, amount) = product.storeProduct.priceCurrencyAndAmount + let duration = product.months // addAppLogEvent(postbox: self.context.account.postbox, type: "premium.promo_screen_accept") @@ -829,7 +859,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { |> deliverOnMainQueue).start(next: { [weak self] available in if let strongSelf = self { if available { - strongSelf.paymentDisposable.set((inAppPurchaseManager.buyProduct(product, targetPeerId: strongSelf.peerId) + 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) @@ -852,7 +882,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { strongSelf.updated(transition: .immediate) - addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail") +// 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 @@ -896,7 +926,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { } if let errorText = errorText { - addAppLogEvent(postbox: strongSelf.context.account.postbox, type: "premium.promo_screen_fail") +// 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) @@ -919,7 +949,7 @@ private final class PremiumGiftScreenComponent: CombinedComponent { } func makeState() -> State { - return State(context: self.context, peerId: self.peerId, updateInProgress: self.updateInProgress, present: self.present, completion: self.completion) + return State(context: self.context, peerId: self.peerId, options: self.options, updateInProgress: self.updateInProgress, present: self.present, completion: self.completion) } static var body: Body { @@ -1242,6 +1272,7 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { super.init(context: context, component: PremiumGiftScreenComponent( context: context, peerId: peerId, + options: options, updateInProgress: { inProgress in updateInProgressImpl?(inProgress) }, diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index 0e266423e0..f3ebc8cbe4 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -1220,7 +1220,7 @@ 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(_:)))) +// self.containerContainingNode.view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:)))) } func updatePresentationData(_ presentationData: PresentationData) { diff --git a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift index 937e1b1fdc..6340b68b50 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -165,9 +165,9 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { duration = item.presentationData.strings.Notification_PremiumGift_Subtitle(item.presentationData.strings.Notification_PremiumGift_Months(months)).string switch months { case 12: - animationName = "Gift2" + animationName = "Gift12" case 6: - animationName = "Gift1" + animationName = "Gift6" case 3: animationName = "Gift3" default: From dcaf459f81f8544c82d2cd35c2a45a944295b4bd Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 04:29:37 +0300 Subject: [PATCH 108/113] Fix mic icon color --- .../TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift index 99e4897580..1f82a3b5c3 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift @@ -363,7 +363,7 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto let colorKeys = ["__allcolors__"] var colors: [String: UIColor] = [:] for colorKey in colorKeys { - colors[colorKey] = self.theme.chat.inputPanel.panelControlColor + colors[colorKey] = self.theme.chat.inputPanel.panelControlColor.blitOver(self.theme.chat.inputPanel.inputBackgroundColor, alpha: 1.0) } let _ = animationView.update( From 05f2bf7b850658378f84909d71b997b8f6fc356c Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 05:36:30 +0300 Subject: [PATCH 109/113] Various fixes --- .../Telegram-iOS/en.lproj/Localizable.strings | 6 + .../Sources/Items/ChatImageGalleryItem.swift | 30 +-- .../Items/UniversalVideoGalleryItem.swift | 30 +-- .../ImportStickerPackControllerNode.swift | 2 +- .../PremiumUI/Sources/PremiumGiftScreen.swift | 4 +- .../InstalledStickerPacksController.swift | 52 ++--- .../Sources/StickerPackScreen.swift | 196 +++++++++--------- .../TelegramUI/Sources/ChatController.swift | 33 ++- .../TelegramUI/Sources/OpenChatMessage.swift | 53 +++-- .../TelegramUI/Sources/OpenResolvedUrl.swift | 38 ++-- 10 files changed, 249 insertions(+), 195 deletions(-) diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index 1b69ca55e6..9aea810170 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -7886,6 +7886,12 @@ Sorry for the inconvenience."; "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."; 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 d586315cdc..66b2bbf180 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -2667,20 +2667,22 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } 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: { 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: 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: + 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)) + } } }, dismissed: { [weak self] in self?.isInteractingPromise.set(false) diff --git a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift index 25d12f558d..163dadd050 100644 --- a/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift +++ b/submodules/ImportStickerPackUI/Sources/ImportStickerPackControllerNode.swift @@ -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/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index c85674f73b..f081acd905 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -820,7 +820,9 @@ private final class PremiumGiftScreenComponent: CombinedComponent { } strongSelf.products = gifts - strongSelf.selectedProductId = strongSelf.products?.first?.id + if strongSelf.selectedProductId == nil { + strongSelf.selectedProductId = strongSelf.products?.first?.id + } strongSelf.peer = peer strongSelf.updated(transition: .immediate) } diff --git a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift index f24eedbc3a..73d10a8f52 100644 --- a/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift +++ b/submodules/SettingsUI/Sources/Stickers/InstalledStickerPacksController.swift @@ -1267,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: [mainStickerPack], 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?() { @@ -1278,31 +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): - 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 - } - - 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() + 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/StickerPackPreviewUI/Sources/StickerPackScreen.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift index f3ebc8cbe4..96786183cb 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackScreen.swift @@ -632,14 +632,15 @@ private final class StickerPackContainer: ASDisplayNode { }) } } 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() -// if dismissed { -// actionPerformed?(info, items, .add) -// } } } + + self.controller?.actionPerformed?(installedPacks) } self.requestDismiss() } else if let (info, items, installed) = self.currentStickerPack { @@ -660,13 +661,13 @@ private final class StickerPackContainer: ASDisplayNode { return } if dismissed { - actionPerformed?(info, items, .remove(positionInList: positionInList)) + actionPerformed?([(info, items, .remove(positionInList: positionInList))]) } }) } else { let _ = self.context.engine.stickers.addStickerPackInteractively(info: info, items: items).start() if dismissed { - actionPerformed?(info, items, .add) + actionPerformed?([(info, items, .add)]) } } } else { @@ -1220,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) { @@ -1238,11 +1238,7 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { transition.updateFrame(node: self.containerContainingNode, frame: CGRect(origin: CGPoint(), size: layout.size)) let expandProgress: CGFloat = 1.0 -// if self.stickerPacks.count == 1 { -// expandProgress = 1.0 -// } else { -// expandProgress = self.containers[self.selectedStickerPackIndex]?.expandProgress ?? 0.0 -// } + let scaledInset: CGFloat = 12.0 let scaledDistance: CGFloat = 4.0 let minScale = (layout.size.width - scaledInset * 2.0) / layout.size.width @@ -1250,108 +1246,106 @@ private final class StickerPackScreenNode: ViewControllerTracingNode { let containerVerticalOffset: CGFloat = (1.0 - expandProgress) * scaledInset * 2.0 -// for i in 0 ..< self.stickerPacks.count { 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 - - 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 - } - } else { + 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, 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) + } + } if firstTime { if !self.containers.isEmpty { @@ -1515,7 +1509,7 @@ public final class StickerPackScreenImpl: ViewController { } 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 { @@ -1530,7 +1524,7 @@ public final class StickerPackScreenImpl: ViewController { 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) { + 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 @@ -1709,7 +1703,7 @@ 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, UIView, CGRect) -> Bool)? = nil, actionPerformed: ((StickerPackCollectionInfo, [StickerPackItem], StickerPackScreenPerformedAction) -> Void)? = nil, dismissed: (() -> Void)? = nil) -> ViewController { +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 diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index a2a53e4bb1..a272a3edce 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -1128,7 +1128,36 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G return } strongSelf.chatDisplayNode.dismissTextInput() - let controller = StickerPackScreen(context: context, updatedPresentationData: strongSelf.updatedPresentationData, mainStickerPack: packReference, stickerPacks: Array(packReferences), parentNavigationController: strongSelf.effectiveNavigationController) + + 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)) } @@ -9412,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 { diff --git a/submodules/TelegramUI/Sources/OpenChatMessage.swift b/submodules/TelegramUI/Sources/OpenChatMessage.swift index 640dce7dfd..09118aa5dc 100644 --- a/submodules/TelegramUI/Sources/OpenChatMessage.swift +++ b/submodules/TelegramUI/Sources/OpenChatMessage.swift @@ -78,31 +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 isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks - + 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: 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 - })) + 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 d981e2ffcb..a945582f78 100644 --- a/submodules/TelegramUI/Sources/OpenResolvedUrl.swift +++ b/submodules/TelegramUI/Sources/OpenResolvedUrl.swift @@ -166,21 +166,29 @@ func openResolvedUrlImpl(_ resolvedUrl: ResolvedUrl, context: AccountContext, ur case let .stickerPack(name, _): dismissInput() - let controller = StickerPackScreen(context: context, updatedPresentationData: updatedPresentationData, mainStickerPack: .name(name), stickerPacks: [.name(name)], parentNavigationController: navigationController, sendSticker: sendSticker, actionPerformed: { info, items, action in - let isEmoji = info.id.namespace == Namespaces.ItemCollection.CloudEmojiPacks - - switch action { - case .add: - 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: 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) + 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 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: 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: 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) From ac36f81827651ee38562ad7345a303d6f0b3ffaa Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 06:03:58 +0300 Subject: [PATCH 110/113] Various fixes --- .../Sources/StickerPackPreviewGridItem.swift | 9 +++++---- .../ChatTextInputMediaRecordingButton.swift | 14 ++++++++++---- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift index 9c5f66cdef..e9805d04c4 100644 --- a/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift +++ b/submodules/StickerPackPreviewUI/Sources/StickerPackPreviewGridItem.swift @@ -192,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) @@ -321,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, *) { @@ -330,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) } } } diff --git a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift index 1f82a3b5c3..62327618b4 100644 --- a/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift +++ b/submodules/TelegramUI/Sources/ChatTextInputMediaRecordingButton.swift @@ -497,8 +497,11 @@ final class ChatTextInputMediaRecordingButton: TGModernConversationInputMicButto micDecoration.isHidden = false micDecoration.startAnimating() - self.animationView.view?.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.15, removeOnCompletion: false) - self.animationView.view?.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) { @@ -510,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) - self.animationView.view?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.15, removeOnCompletion: false) - self.animationView.view?.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) + } } } From 0b41dff8f8eafeb65bc7cafa16baa7a109b24ec7 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 07:27:42 +0300 Subject: [PATCH 111/113] Various fixes --- .../Sources/ChatController.swift | 2 ++ .../PremiumUI/Sources/PremiumGiftScreen.swift | 6 ++++++ .../TelegramUI/Sources/ChatController.swift | 4 ++++ .../Sources/ChatControllerInteraction.swift | 1 + .../Sources/ChatMessageGiftItemNode.swift | 20 +++++++++---------- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/submodules/AccountContext/Sources/ChatController.swift b/submodules/AccountContext/Sources/ChatController.swift index ac9c4521d2..764839370a 100644 --- a/submodules/AccountContext/Sources/ChatController.swift +++ b/submodules/AccountContext/Sources/ChatController.swift @@ -560,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/PremiumUI/Sources/PremiumGiftScreen.swift b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift index f081acd905..bb59828aab 100644 --- a/submodules/PremiumUI/Sources/PremiumGiftScreen.swift +++ b/submodules/PremiumUI/Sources/PremiumGiftScreen.swift @@ -1311,6 +1311,12 @@ public final class PremiumGiftScreen: ViewControllerComponentContainer { 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) } } diff --git a/submodules/TelegramUI/Sources/ChatController.swift b/submodules/TelegramUI/Sources/ChatController.swift index a272a3edce..132c6f37d9 100644 --- a/submodules/TelegramUI/Sources/ChatController.swift +++ b/submodules/TelegramUI/Sources/ChatController.swift @@ -16333,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 diff --git a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift index 2267e19977..75332b03d1 100644 --- a/submodules/TelegramUI/Sources/ChatControllerInteraction.swift +++ b/submodules/TelegramUI/Sources/ChatControllerInteraction.swift @@ -160,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, diff --git a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift index 6340b68b50..f8240bd04d 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -41,8 +41,6 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { private var absoluteRect: (CGRect, CGSize)? private var isPlaying: Bool = false - private var wasPending: Bool = false - private var didChangeFromPendingToSent: Bool = false override var visibility: ListViewItemNodeVisibility { didSet { @@ -227,13 +225,7 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { strongSelf.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 384, height: 384, playbackMode: .still(.end), mode: .direct(cachePathPrefix: nil)) } strongSelf.item = item - - if item.message.id.namespace == Namespaces.Message.Local || item.message.id.namespace == Namespaces.Message.ScheduledLocal { - strongSelf.wasPending = true - } - if strongSelf.wasPending && (item.message.id.namespace != Namespaces.Message.Local && item.message.id.namespace != Namespaces.Message.ScheduledLocal) { - strongSelf.didChangeFromPendingToSent = true - } + strongSelf.updateVisibility() strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) @@ -438,13 +430,21 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { } } + if !item.message.effectivelyIncoming(item.context.account.peerId) + && 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 { - item.controllerInteraction.animateDiceSuccess(false, true) + Queue.mainQueue().after(1.0) { + item.controllerInteraction.animateDiceSuccess(false, true) + } } } } From 5591fd9eb0c9659bd57d517977ede63bdaee75c1 Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 07:48:13 +0300 Subject: [PATCH 112/113] Various fixes --- .../Sources/ChatMessageGiftItemNode.swift | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift index f8240bd04d..f0287d959b 100644 --- a/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageGiftItemNode.swift @@ -408,6 +408,10 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { } } + override func unreadMessageRangeUpdated() { + self.updateVisibility() + } + private func updateVisibility() { guard let item = self.item else { return @@ -422,18 +426,16 @@ class ChatMessageGiftBubbleContentNode: ChatMessageBubbleContentNode { if isPlaying { var alreadySeen = true - if let unreadRange = item.controllerInteraction.unreadMessageRange[UnreadMessageRangeKey(peerId: item.message.id.peerId, namespace: item.message.id.namespace)] { - if unreadRange.contains(item.message.id.id) { - if !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.id) { + 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 } } - } - - if !item.message.effectivelyIncoming(item.context.account.peerId) - && item.controllerInteraction.playNextOutgoingGift - && !item.controllerInteraction.seenOneTimeAnimatedMedia.contains(item.message.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) { From 495a336be846bb59dcbba1c569515f5d044b1bfe Mon Sep 17 00:00:00 2001 From: Ilya Laktyushin Date: Mon, 25 Jul 2022 07:49:39 +0300 Subject: [PATCH 113/113] Bump version --- versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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" }