diff --git a/Telegram/Telegram-iOS/en.lproj/Localizable.strings b/Telegram/Telegram-iOS/en.lproj/Localizable.strings index b077464c25..4bd7ef1dcc 100644 --- a/Telegram/Telegram-iOS/en.lproj/Localizable.strings +++ b/Telegram/Telegram-iOS/en.lproj/Localizable.strings @@ -11594,3 +11594,13 @@ Sorry for the inconvenience."; "Chat.QuickReplyMediaMessageLimitReachedText_1" = "There can be at most %d message in this chat."; "Chat.QuickReplyMediaMessageLimitReachedText_any" = "There can be at most %d messages in this chat."; + +"CollectibleItemInfo.StoreName" = "Fragment"; +"CollectibleItemInfo.UsernameTitle" = "%@ is a collectible username that belongs to"; +"CollectibleItemInfo.UsernameText" = "The %1$@ username was acquired on %2$@ on %3$@ for %4$@ (%5$@)."; +"CollectibleItemInfo.PhoneTitle" = "%@ is a collectible phone number that belongs to"; +"CollectibleItemInfo.PhoneText" = "The %1$@ phone number was acquired on %2$@ on %3$@ for %4$@ (%5$@)."; +"CollectibleItemInfo.ButtonOpenInfo" = "Learn More"; +"CollectibleItemInfo.ButtonCopyUsername" = "Copy Link"; +"CollectibleItemInfo.ButtonCopyPhone" = "Copy Phone Number"; +"CollectibleItemInfo.ShareInlineText.LearnMore" = "Learn more >"; diff --git a/submodules/AccountContext/Sources/AccountContext.swift b/submodules/AccountContext/Sources/AccountContext.swift index bdb918f337..c4ff2f093d 100644 --- a/submodules/AccountContext/Sources/AccountContext.swift +++ b/submodules/AccountContext/Sources/AccountContext.swift @@ -101,7 +101,7 @@ public enum TextLinkItemActionType { case longTap } -public enum TextLinkItem { +public enum TextLinkItem: Equatable { case url(url: String, concealed: Bool) case mention(String) case hashtag(String?, String) @@ -856,6 +856,15 @@ public protocol AutomaticBusinessMessageSetupScreenInitialData: AnyObject { public protocol ChatbotSetupScreenInitialData: AnyObject { } +public protocol CollectibleItemInfoScreenInitialData: AnyObject { + var collectibleItemInfo: TelegramCollectibleItemInfo { get } +} + +public enum CollectibleItemInfoScreenSubject { + case phoneNumber(String) + case username(String) +} + public protocol SharedAccountContext: AnyObject { var sharedContainerPath: String { get } var basePath: String { get } @@ -951,6 +960,8 @@ public protocol SharedAccountContext: AnyObject { func makeAutomaticBusinessMessageSetupScreenInitialData(context: AccountContext) -> Signal func makeQuickReplySetupScreen(context: AccountContext, initialData: QuickReplySetupScreenInitialData) -> ViewController func makeQuickReplySetupScreenInitialData(context: AccountContext) -> Signal + func makeCollectibleItemInfoScreen(context: AccountContext, initialData: CollectibleItemInfoScreenInitialData) -> ViewController + func makeCollectibleItemInfoScreenInitialData(context: AccountContext, peerId: EnginePeer.Id, subject: CollectibleItemInfoScreenSubject) -> Signal func navigateToChatController(_ params: NavigateToChatControllerParams) func navigateToForumChannel(context: AccountContext, peerId: EnginePeer.Id, navigationController: NavigationController) func navigateToForumThread(context: AccountContext, peerId: EnginePeer.Id, threadId: Int64, messageId: EngineMessage.Id?, navigationController: NavigationController, activateInput: ChatControllerActivateInput?, keepStack: NavigateToChatKeepStack) -> Signal diff --git a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift index f6412b6200..756cd33f56 100644 --- a/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift +++ b/submodules/JoinLinkPreviewUI/Sources/JoinLinkPreviewPeerContentNode.swift @@ -91,6 +91,7 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer } } + private var contentDidBeginDragging: (() -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private let avatarNode: AvatarNode @@ -220,6 +221,10 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?) { } + func setDidBeginDragging(_ f: (() -> Void)?) { + self.contentDidBeginDragging = f + } + func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } @@ -385,6 +390,7 @@ public enum ShareLoadingState { } public final class JoinLinkPreviewLoadingContainerNode: ASDisplayNode, ShareContentContainerNode { + private var contentDidBeginDragging: (() -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private var theme: PresentationTheme @@ -408,6 +414,10 @@ public final class JoinLinkPreviewLoadingContainerNode: ASDisplayNode, ShareCont public func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?) { } + public func setDidBeginDragging(_ f: (() -> Void)?) { + self.contentDidBeginDragging = f + } + public func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } diff --git a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewContentNode.swift b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewContentNode.swift index 13ebb8e9bd..e4c691aff3 100644 --- a/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewContentNode.swift +++ b/submodules/LanguageLinkPreviewUI/Sources/LanguageLinkPreviewContentNode.swift @@ -78,6 +78,9 @@ final class LanguageLinkPreviewContentNode: ASDisplayNode, ShareContentContainer func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?) { } + func setDidBeginDragging(_ f: (() -> Void)?) { + } + func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } diff --git a/submodules/ShareController/BUILD b/submodules/ShareController/BUILD index 8d91ce2463..439be0fa1f 100644 --- a/submodules/ShareController/BUILD +++ b/submodules/ShareController/BUILD @@ -40,6 +40,9 @@ swift_library( "//submodules/TelegramUI/Components/AnimationCache", "//submodules/TelegramUI/Components/MultiAnimationRenderer", "//submodules/UndoUI", + "//submodules/Components/MultilineTextComponent", + "//submodules/Components/BundleIconComponent", + "//submodules/TelegramUI/Components/LottieComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/ShareController/Sources/ShareContentContainerNode.swift b/submodules/ShareController/Sources/ShareContentContainerNode.swift index 57179bcf47..fe14148588 100644 --- a/submodules/ShareController/Sources/ShareContentContainerNode.swift +++ b/submodules/ShareController/Sources/ShareContentContainerNode.swift @@ -8,6 +8,7 @@ public protocol ShareContentContainerNode: AnyObject { func activate() func deactivate() func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?) + func setDidBeginDragging(_ f: (() -> Void)?) func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) func updateTheme(_ theme: PresentationTheme) diff --git a/submodules/ShareController/Sources/ShareController.swift b/submodules/ShareController/Sources/ShareController.swift index 8dde82352f..e77387018c 100644 --- a/submodules/ShareController/Sources/ShareController.swift +++ b/submodules/ShareController/Sources/ShareController.swift @@ -450,6 +450,7 @@ public final class ShareController: ViewController { private let immediatePeerId: PeerId? private let segmentedValues: [ShareControllerSegmentedValue]? private let fromForeignApp: Bool + private let collectibleItemInfo: TelegramCollectibleItemInfo? private let peers = Promise<([(peer: EngineRenderedPeer, presence: EnginePeer.Presence?, requiresPremiumForMessaging: Bool)], EnginePeer)>() private let peersDisposable = MetaDisposable() @@ -484,7 +485,7 @@ public final class ShareController: ViewController { public var parentNavigationController: NavigationController? - public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil, shareAsLink: Bool = false) { + public convenience init(context: AccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [AccountWithInfo] = [], immediatePeerId: PeerId? = nil, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil, shareAsLink: Bool = false, collectibleItemInfo: TelegramCollectibleItemInfo? = nil) { self.init( environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), currentContext: ShareControllerAppAccountContext(context: context), @@ -503,11 +504,12 @@ public final class ShareController: ViewController { updatedPresentationData: updatedPresentationData, forceTheme: forceTheme, forcedActionTitle: forcedActionTitle, - shareAsLink: shareAsLink + shareAsLink: shareAsLink, + collectibleItemInfo: collectibleItemInfo ) } - public init(environment: ShareControllerEnvironment, currentContext: ShareControllerAccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [ShareControllerSwitchableAccount] = [], immediatePeerId: PeerId? = nil, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil, shareAsLink: Bool = false) { + public init(environment: ShareControllerEnvironment, currentContext: ShareControllerAccountContext, subject: ShareControllerSubject, presetText: String? = nil, preferredAction: ShareControllerPreferredAction = .default, showInChat: ((Message) -> Void)? = nil, fromForeignApp: Bool = false, segmentedValues: [ShareControllerSegmentedValue]? = nil, externalShare: Bool = true, immediateExternalShare: Bool = false, switchableAccounts: [ShareControllerSwitchableAccount] = [], immediatePeerId: PeerId? = nil, updatedPresentationData: (initial: PresentationData, signal: Signal)? = nil, forceTheme: PresentationTheme? = nil, forcedActionTitle: String? = nil, shareAsLink: Bool = false, collectibleItemInfo: TelegramCollectibleItemInfo? = nil) { self.environment = environment self.currentContext = currentContext self.subject = subject @@ -520,6 +522,7 @@ public final class ShareController: ViewController { self.segmentedValues = segmentedValues self.forceTheme = forceTheme self.shareAsLink = shareAsLink + self.collectibleItemInfo = collectibleItemInfo self.presentationData = updatedPresentationData?.initial ?? environment.presentationData if let forceTheme = self.forceTheme { @@ -717,7 +720,7 @@ public final class ShareController: ViewController { return } strongSelf.present(standardTextAlertController(theme: AlertControllerTheme(presentationData: strongSelf.presentationData), title: title, text: text, actions: [TextAlertAction(type: .defaultAction, title: strongSelf.presentationData.strings.Common_OK, action: {})]), in: .window(.root)) - }, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare, immediatePeerId: self.immediatePeerId, fromForeignApp: self.fromForeignApp, forceTheme: self.forceTheme, fromPublicChannel: fromPublicChannel, segmentedValues: self.segmentedValues, shareStory: self.shareStory) + }, externalShare: self.externalShare, immediateExternalShare: self.immediateExternalShare, immediatePeerId: self.immediatePeerId, fromForeignApp: self.fromForeignApp, forceTheme: self.forceTheme, fromPublicChannel: fromPublicChannel, segmentedValues: self.segmentedValues, shareStory: self.shareStory, collectibleItemInfo: self.collectibleItemInfo) self.controllerNode.completed = self.completed self.controllerNode.enqueued = self.enqueued self.controllerNode.present = { [weak self] c in diff --git a/submodules/ShareController/Sources/ShareControllerNode.swift b/submodules/ShareController/Sources/ShareControllerNode.swift index 673cb12c01..6c3ab733c3 100644 --- a/submodules/ShareController/Sources/ShareControllerNode.swift +++ b/submodules/ShareController/Sources/ShareControllerNode.swift @@ -9,6 +9,11 @@ import TelegramPresentationData import AccountContext import TelegramIntents import ContextUI +import ComponentFlow +import MultilineTextComponent +import TelegramStringFormatting +import BundleIconComponent +import LottieComponent enum ShareState { case preparing(Bool) @@ -21,6 +26,276 @@ enum ShareExternalState { case done } +private final class ShareContentInfoView: UIView { + private struct Params: Equatable { + var environment: ShareControllerEnvironment + var theme: PresentationTheme + var strings: PresentationStrings + var collectibleItemInfo: TelegramCollectibleItemInfo + var availableSize: CGSize + + init(environment: ShareControllerEnvironment, theme: PresentationTheme, strings: PresentationStrings, collectibleItemInfo: TelegramCollectibleItemInfo, availableSize: CGSize) { + self.environment = environment + self.theme = theme + self.strings = strings + self.collectibleItemInfo = collectibleItemInfo + self.availableSize = availableSize + } + + static func ==(lhs: Params, rhs: Params) -> Bool { + if lhs.environment !== rhs.environment { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.strings !== rhs.strings { + return false + } + if lhs.collectibleItemInfo != rhs.collectibleItemInfo { + return false + } + if lhs.availableSize != rhs.availableSize { + return false + } + return true + } + } + + private struct Layout { + var params: Params + var size: CGSize + + init(params: Params, size: CGSize) { + self.params = params + self.size = size + } + } + + private let icon = ComponentView() + private let text = ComponentView() + private var currencySymbolIcon: UIImage? + private var arrowIcon: UIImage? + private let backgroundView: BlurredBackgroundView + + private var currentLayout: Layout? + + override init(frame: CGRect) { + self.backgroundView = BlurredBackgroundView(color: nil, enableBlur: true) + + super.init(frame: frame) + + self.addSubview(self.backgroundView) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(environment: ShareControllerEnvironment, presentationData: PresentationData, collectibleItemInfo: TelegramCollectibleItemInfo, availableSize: CGSize) -> CGSize { + let params = Params( + environment: environment, + theme: presentationData.theme, + strings: presentationData.strings, + collectibleItemInfo: collectibleItemInfo, + availableSize: availableSize + ) + if let currentLayout = self.currentLayout, currentLayout.params == params { + return currentLayout.size + } + let size = self.updateInternal(params: params) + self.currentLayout = Layout(params: params, size: size) + return size + } + + private func updateInternal(params: Params) -> CGSize { + var username: String = "" + if case let .username(value) = params.collectibleItemInfo.subject { + username = value + } + + let textText = NSMutableAttributedString() + + let dateText = stringForDate(timestamp: params.collectibleItemInfo.purchaseDate, strings: params.strings) + + let (rawCryptoCurrencyText, cryptoCurrencySign, _) = formatCurrencyAmountCustom(params.collectibleItemInfo.cryptoCurrencyAmount, currency: params.collectibleItemInfo.cryptoCurrency, customFormat: CurrencyFormatterEntry( + symbol: "~", + thousandsSeparator: ",", + decimalSeparator: ".", + symbolOnLeft: true, + spaceBetweenAmountAndSymbol: false, + decimalDigits: 9 + )) + var cryptoCurrencyText = rawCryptoCurrencyText + while cryptoCurrencyText.hasSuffix("0") { + cryptoCurrencyText = String(cryptoCurrencyText[cryptoCurrencyText.startIndex ..< cryptoCurrencyText.index(before: cryptoCurrencyText.endIndex)]) + } + if cryptoCurrencyText.hasSuffix(".") { + cryptoCurrencyText = String(cryptoCurrencyText[cryptoCurrencyText.startIndex ..< cryptoCurrencyText.index(before: cryptoCurrencyText.endIndex)]) + } + + let (currencyText, currencySign, _) = formatCurrencyAmountCustom(params.collectibleItemInfo.currencyAmount, currency: params.collectibleItemInfo.currency) + + let rawTextString = params.strings.CollectibleItemInfo_UsernameText("@\(username)", params.strings.CollectibleItemInfo_StoreName, dateText, "\(cryptoCurrencySign)\(cryptoCurrencyText)", "\(currencySign)\(currencyText)") + textText.append(NSAttributedString(string: rawTextString.string, font: Font.regular(14.0), textColor: .white)) + for range in rawTextString.ranges { + switch range.index { + case 0: + textText.addAttribute(.font, value: Font.semibold(14.0), range: range.range) + case 1: + textText.addAttribute(.font, value: Font.semibold(14.0), range: range.range) + case 3: + textText.addAttribute(.font, value: Font.semibold(14.0), range: range.range) + default: + break + } + } + + let currencySymbolRange = (textText.string as NSString).range(of: "~") + + if self.currencySymbolIcon == nil { + if let templateImage = UIImage(bundleImageName: "Peer Info/CollectibleTonSymbolInline") { + self.currencySymbolIcon = generateImage(CGSize(width: templateImage.size.width, height: templateImage.size.height + 2.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + if let cgImage = templateImage.cgImage { + context.draw(cgImage, in: CGRect(origin: CGPoint(x: 0.0, y: 4.0), size: CGSize(width: templateImage.size.width - 2.0, height: templateImage.size.height - 2.0))) + } + })?.withRenderingMode(.alwaysTemplate) + } + } + + if currencySymbolRange.location != NSNotFound, let currencySymbolIcon = self.currencySymbolIcon { + textText.replaceCharacters(in: currencySymbolRange, with: "$") + textText.addAttribute(.attachment, value: currencySymbolIcon, range: currencySymbolRange) + + 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 + } + } + let font = Font.semibold(14.0) + let runDelegateData = RunDelegateData( + ascent: font.ascender, + descent: font.descender, + width: currencySymbolIcon.size.width + 4.0 + ) + var callbacks = CTRunDelegateCallbacks( + version: kCTRunDelegateCurrentVersion, + dealloc: { dataRef in + Unmanaged.fromOpaque(dataRef).release() + }, + getAscent: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().ascent + }, + getDescent: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().descent + }, + getWidth: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().width + } + ) + + if let runDelegate = CTRunDelegateCreate(&callbacks, Unmanaged.passRetained(runDelegateData).toOpaque()) { + textText.addAttribute(NSAttributedString.Key(rawValue: kCTRunDelegateAttributeName as String), value: runDelegate, range: currencySymbolRange) + } + } + + let accentColor = params.theme.list.itemAccentColor.withMultiplied(hue: 0.933, saturation: 0.61, brightness: 1.0) + if self.arrowIcon == nil { + if let templateImage = UIImage(bundleImageName: "Settings/TextArrowRight") { + let scaleFactor: CGFloat = 0.8 + let imageSize = CGSize(width: floor(templateImage.size.width * scaleFactor), height: floor(templateImage.size.height * scaleFactor)) + self.arrowIcon = generateImage(imageSize, contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + if let cgImage = templateImage.cgImage { + context.draw(cgImage, in: CGRect(origin: CGPoint(), size: size)) + } + })?.withRenderingMode(.alwaysTemplate) + } + } + + textText.append(NSAttributedString(string: "\n\(params.strings.CollectibleItemInfo_ShareInlineText_LearnMore)", attributes: [ + .font: Font.medium(14.0), + .foregroundColor: accentColor, + NSAttributedString.Key(rawValue: "URL"): "" + ])) + if let range = textText.string.range(of: ">"), let arrowIcon = self.arrowIcon { + textText.addAttribute(.attachment, value: arrowIcon, range: NSRange(range, in: textText.string)) + } + + let textInsets = UIEdgeInsets(top: 8.0, left: 50.0, bottom: 8.0, right: 10.0) + + let textSize = self.text.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(textText), + maximumNumberOfLines: 0, + lineSpacing: 0.185, + highlightColor: accentColor.withMultipliedAlpha(0.1), + highlightAction: { attributes in + if let _ = attributes[NSAttributedString.Key(rawValue: "URL")] { + return NSAttributedString.Key(rawValue: "URL") + } else { + return nil + } + }, + tapAction: { [weak self] _, _ in + guard let self, let params = self.currentLayout?.params else { + return + } + if let environment = params.environment as? ShareControllerAppEnvironment { + environment.sharedContext.applicationBindings.openUrl(params.collectibleItemInfo.url) + } + } + )), + environment: {}, + containerSize: CGSize(width: params.availableSize.width - textInsets.left - textInsets.right, height: 1000.0) + ) + let textFrame = CGRect(origin: CGPoint(x: textInsets.left, y: textInsets.top), size: textSize) + if let textView = self.text.view { + if textView.superview == nil { + self.addSubview(textView) + } + textView.frame = textFrame + } + + let size = CGSize(width: params.availableSize.width, height: textInsets.top + textSize.height + textInsets.bottom) + + let iconSize = self.icon.update( + transition: .immediate, + component: AnyComponent(LottieComponent( + content: LottieComponent.AppBundleContent(name: "ToastCollectibleUsernameEmoji"), + loop: false + )), + environment: {}, + containerSize: CGSize(width: 30.0, height: 30.0) + ) + let iconFrame = CGRect(origin: CGPoint(x: floor((textInsets.left - iconSize.width) * 0.5), y: floor((size.height - iconSize.height) * 0.5)), size: iconSize) + if let iconView = self.icon.view as? LottieComponent.View { + if iconView.superview == nil { + self.addSubview(iconView) + iconView.playOnce(delay: 0.1) + } + iconView.frame = iconFrame + } + + self.backgroundView.updateColor(color: UIColor(rgb: 0x1C2023), transition: .immediate) + self.backgroundView.update(size: size, cornerRadius: 16.0, transition: .immediate) + self.backgroundView.frame = CGRect(origin: CGPoint(), size: size) + + return size + } +} + final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate { private weak var controller: ShareController? private let environment: ShareControllerEnvironment @@ -33,6 +308,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate private let fromForeignApp: Bool private let fromPublicChannel: Bool private let segmentedValues: [ShareControllerSegmentedValue]? + private let collectibleItemInfo: TelegramCollectibleItemInfo? var selectedSegmentedIndex: Int = 0 private let defaultAction: ShareControllerAction? @@ -48,6 +324,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate private let contentContainerNode: ASDisplayNode private let contentBackgroundNode: ASImageNode + private var contentInfoView: ShareContentInfoView? private var contentNode: (ASDisplayNode & ShareContentContainerNode)? private var previousContentNode: (ASDisplayNode & ShareContentContainerNode)? @@ -90,7 +367,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate private let showNames = ValuePromise(true) - init(controller: ShareController, environment: ShareControllerEnvironment, presentationData: PresentationData, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forceTheme: PresentationTheme?, fromPublicChannel: Bool, segmentedValues: [ShareControllerSegmentedValue]?, shareStory: (() -> Void)?) { + init(controller: ShareController, environment: ShareControllerEnvironment, presentationData: PresentationData, presetText: String?, defaultAction: ShareControllerAction?, requestLayout: @escaping (ContainedViewLayoutTransition) -> Void, presentError: @escaping (String?, String) -> Void, externalShare: Bool, immediateExternalShare: Bool, immediatePeerId: PeerId?, fromForeignApp: Bool, forceTheme: PresentationTheme?, fromPublicChannel: Bool, segmentedValues: [ShareControllerSegmentedValue]?, shareStory: (() -> Void)?, collectibleItemInfo: TelegramCollectibleItemInfo?) { self.controller = controller self.environment = environment self.presentationData = presentationData @@ -102,6 +379,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate self.presentError = presentError self.fromPublicChannel = fromPublicChannel self.segmentedValues = segmentedValues + self.collectibleItemInfo = collectibleItemInfo self.presetText = presetText @@ -156,6 +434,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate self.contentBackgroundNode.displayWithoutProcessing = true self.contentBackgroundNode.image = roundedBackground + self.contentInfoView = ShareContentInfoView(frame: CGRect()) + self.actionsBackgroundNode = ASImageNode() self.actionsBackgroundNode.isLayerBacked = true self.actionsBackgroundNode.displayWithoutProcessing = true @@ -356,6 +636,10 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate self.wrappingScrollNode.addSubnode(self.contentBackgroundNode) + if let contentInfoView = self.contentInfoView { + self.wrappingScrollNode.view.addSubview(contentInfoView) + } + self.wrappingScrollNode.addSubnode(self.contentContainerNode) self.contentContainerNode.addSubnode(self.actionSeparatorNode) self.contentContainerNode.addSubnode(self.actionsBackgroundNode) @@ -433,12 +717,14 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } if let searchContentNode = strongSelf.contentNode as? ShareSearchContainerNode { + searchContentNode.setDidBeginDragging(nil) searchContentNode.setContentOffsetUpdated(nil) let scrollDelta = topicsContentNode.contentGridNode.scrollView.contentOffset.y - searchContentNode.contentGridNode.scrollView.contentOffset.y if let sourceFrame = searchContentNode.animateOut(peerId: peer.peerId, scrollDelta: scrollDelta) { topicsContentNode.animateIn(sourceFrame: sourceFrame, scrollDelta: scrollDelta) } } else if let peersContentNode = strongSelf.peersContentNode { + peersContentNode.setDidBeginDragging(nil) peersContentNode.setContentOffsetUpdated(nil) let scrollDelta = topicsContentNode.contentGridNode.scrollView.contentOffset.y - peersContentNode.contentGridNode.scrollView.contentOffset.y if let sourceFrame = peersContentNode.animateOut(peerId: peer.peerId, scrollDelta: scrollDelta) { @@ -446,6 +732,9 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } } + topicsContentNode.setDidBeginDragging({ [weak self] in + self?.contentNodeDidBeginDragging() + }) topicsContentNode.setContentOffsetUpdated({ [weak self] contentOffset, transition in self?.contentNodeOffsetUpdated(contentOffset, transition: transition) }) @@ -459,6 +748,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate guard let topicsContentNode = self.topicsContentNode else { return } + topicsContentNode.setDidBeginDragging(nil) topicsContentNode.setContentOffsetUpdated(nil) if let searchContentNode = self.contentNode as? ShareSearchContainerNode { @@ -472,6 +762,9 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } if let searchContentNode = self.contentNode as? ShareSearchContainerNode { + searchContentNode.setDidBeginDragging({ [weak self] in + self?.contentNodeDidBeginDragging() + }) searchContentNode.setContentOffsetUpdated({ [weak self] contentOffset, transition in self?.contentNodeOffsetUpdated(contentOffset, transition: transition) }) @@ -487,6 +780,9 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate }) } } else if let peersContentNode = self.peersContentNode { + peersContentNode.setDidBeginDragging({ [weak self] in + self?.contentNodeDidBeginDragging() + }) peersContentNode.setContentOffsetUpdated({ [weak self] contentOffset, transition in self?.contentNodeOffsetUpdated(contentOffset, transition: transition) }) @@ -579,6 +875,7 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate let previous = self.contentNode if let previous = previous { + previous.setDidBeginDragging(nil) previous.setContentOffsetUpdated(nil) if animated { transition = .animated(duration: 0.4, curve: .spring) @@ -597,6 +894,8 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate previous.removeFromSupernode() self.previousContentNode = nil } + + self.contentNodeDidBeginDragging() } else { transition = .immediate } @@ -607,6 +906,9 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate contentNode.frame = previous.frame contentNode.updateLayout(size: previous.bounds.size, isLandscape: layout.size.width > layout.size.height, bottomInset: bottomGridInset, transition: .immediate) + contentNode.setDidBeginDragging({ [weak self] in + self?.contentNodeDidBeginDragging() + }) contentNode.setContentOffsetUpdated({ [weak self] contentOffset, transition in self?.contentNodeOffsetUpdated(contentOffset, transition: transition) }) @@ -635,6 +937,9 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } } else { if let contentNode = self.contentNode { + contentNode.setDidBeginDragging({ [weak self] in + self?.contentNodeDidBeginDragging() + }) contentNode.setContentOffsetUpdated({ [weak self] contentOffset, transition in self?.contentNodeOffsetUpdated(contentOffset, transition: transition) }) @@ -737,6 +1042,13 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } } + private func contentNodeDidBeginDragging() { + if let contentInfoView = self.contentInfoView, contentInfoView.alpha != 0.0 { + Transition.easeInOut(duration: 0.2).setAlpha(view: contentInfoView, alpha: 0.0) + Transition.easeInOut(duration: 0.2).setScale(view: contentInfoView, scale: 0.5) + } + } + private func contentNodeOffsetUpdated(_ contentOffset: CGFloat, transition: ContainedViewLayoutTransition) { if let (layout, _, _) = self.containerLayout { var insets = layout.insets(options: [.statusBar, .input]) @@ -770,6 +1082,25 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } transition.updateFrame(node: self.contentBackgroundNode, frame: backgroundFrame) + if let contentInfoView = self.contentInfoView, let collectibleItemInfo = self.collectibleItemInfo { + let contentInfoSize = contentInfoView.update( + environment: self.environment, + presentationData: self.presentationData, + collectibleItemInfo: collectibleItemInfo, + availableSize: CGSize(width: backgroundFrame.width, height: 1000.0) + ) + let contentInfoFrame = CGRect(origin: CGPoint(x: backgroundFrame.minX, y: backgroundFrame.minY - 8.0 - contentInfoSize.height), size: contentInfoSize) + + if contentInfoView.bounds.isEmpty { + if contentInfoFrame.minY < 0.0 { + contentInfoView.alpha = 0.0 + } + } + + transition.updatePosition(layer: contentInfoView.layer, position: contentInfoFrame.center) + transition.updateBounds(layer: contentInfoView.layer, bounds: CGRect(origin: CGPoint(), size: contentInfoFrame.size)) + } + if let animateContentNodeOffsetFromBackgroundOffset = self.animateContentNodeOffsetFromBackgroundOffset { self.animateContentNodeOffsetFromBackgroundOffset = nil let offset = backgroundFrame.minY - animateContentNodeOffsetFromBackgroundOffset @@ -1019,6 +1350,11 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate } self.animatingOut = true + if let contentInfoView = self.contentInfoView, contentInfoView.alpha != 0.0 { + Transition.easeInOut(duration: 0.2).setAlpha(view: contentInfoView, alpha: 0.0) + Transition.easeInOut(duration: 0.2).setScale(view: contentInfoView, scale: 0.5) + } + if self.contentNode != nil { var dimCompleted = false var offsetCompleted = false @@ -1223,6 +1559,12 @@ final class ShareControllerNode: ViewControllerTracingNode, UIScrollViewDelegate return result } if self.bounds.contains(point) { + if let contentInfoView = self.contentInfoView, contentInfoView.alpha != 0.0 { + if let result = contentInfoView.hitTest(self.view.convert(point, to: contentInfoView), with: event) { + return result + } + } + if !self.contentBackgroundNode.bounds.contains(self.convert(point, to: self.contentBackgroundNode)) && !self.cancelButtonNode.bounds.contains(self.convert(point, to: self.cancelButtonNode)) { return self.dimNode.view } diff --git a/submodules/ShareController/Sources/ShareLoadingContainerNode.swift b/submodules/ShareController/Sources/ShareLoadingContainerNode.swift index c643f1ef46..1d6c98dede 100644 --- a/submodules/ShareController/Sources/ShareLoadingContainerNode.swift +++ b/submodules/ShareController/Sources/ShareLoadingContainerNode.swift @@ -94,6 +94,9 @@ public final class ShareLoadingContainerNode: ASDisplayNode, ShareContentContain public func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?) { } + public func setDidBeginDragging(_ f: (() -> Void)?) { + } + public func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } @@ -308,6 +311,9 @@ public final class ShareProlongedLoadingContainerNode: ASDisplayNode, ShareConte public func setEnsurePeerVisibleOnLayout(_ peerId: EnginePeer.Id?) { } + public func setDidBeginDragging(_ f: (() -> Void)?) { + } + public func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } diff --git a/submodules/ShareController/Sources/SharePeersContainerNode.swift b/submodules/ShareController/Sources/SharePeersContainerNode.swift index 60e45b0d7f..1d4d9439c0 100644 --- a/submodules/ShareController/Sources/SharePeersContainerNode.swift +++ b/submodules/ShareController/Sources/SharePeersContainerNode.swift @@ -126,6 +126,7 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { private let segmentedValues: [ShareControllerSegmentedValue]? + private var contentDidBeginDragging: (() -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? var openSearch: (() -> Void)? @@ -297,6 +298,10 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { strongSelf.enqueueTransition(transition, firstTime: firstTime) } })) + + self.contentGridNode.scrollingInitiated = { [weak self] in + self?.contentDidBeginDragging?() + } self.contentGridNode.presentationLayoutUpdated = { [weak self] presentationLayout, transition in self?.gridPresentationLayoutUpdated(presentationLayout, transition: transition) @@ -350,6 +355,10 @@ final class SharePeersContainerNode: ASDisplayNode, ShareContentContainerNode { self.ensurePeerVisibleOnLayout = peerId } + func setDidBeginDragging(_ f: (() -> Void)?) { + self.contentDidBeginDragging = f + } + func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } diff --git a/submodules/ShareController/Sources/ShareSearchContainerNode.swift b/submodules/ShareController/Sources/ShareSearchContainerNode.swift index 3376a93e7d..31c048c033 100644 --- a/submodules/ShareController/Sources/ShareSearchContainerNode.swift +++ b/submodules/ShareController/Sources/ShareSearchContainerNode.swift @@ -194,6 +194,7 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { private let searchNode: ShareSearchBarNode private let cancelButtonNode: HighlightableButtonNode + private var contentDidBeginDragging: (() -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? var cancel: (() -> Void)? @@ -240,6 +241,14 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { self.addSubnode(self.cancelButtonNode) self.addSubnode(self.contentSeparatorNode) + self.recentGridNode.scrollingInitiated = { [weak self] in + self?.contentDidBeginDragging?() + } + + self.contentGridNode.scrollingInitiated = { [weak self] in + self?.contentDidBeginDragging?() + } + self.recentGridNode.presentationLayoutUpdated = { [weak self] presentationLayout, transition in if let strongSelf = self, !strongSelf.recentGridNode.isHidden { strongSelf.gridPresentationLayoutUpdated(presentationLayout, transition: transition) @@ -466,6 +475,10 @@ final class ShareSearchContainerNode: ASDisplayNode, ShareContentContainerNode { self.ensurePeerVisibleOnLayout = peerId } + func setDidBeginDragging(_ f: (() -> Void)?) { + self.contentDidBeginDragging = f + } + func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } diff --git a/submodules/ShareController/Sources/ShareTopicsContainerNode.swift b/submodules/ShareController/Sources/ShareTopicsContainerNode.swift index 5319df1494..5462d91491 100644 --- a/submodules/ShareController/Sources/ShareTopicsContainerNode.swift +++ b/submodules/ShareController/Sources/ShareTopicsContainerNode.swift @@ -174,6 +174,7 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode { private let contentSubtitleNode: ASTextNode private let backNode: CancelButtonNode + private var contentDidBeginDragging: (() -> Void)? private var contentOffsetUpdated: ((CGFloat, ContainedViewLayoutTransition) -> Void)? private var validLayout: (CGSize, CGFloat)? @@ -249,6 +250,10 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode { strongSelf.enqueueTransition(transition, firstTime: firstTime) } })) + + self.contentGridNode.scrollingInitiated = { [weak self] in + self?.contentDidBeginDragging?() + } self.contentGridNode.presentationLayoutUpdated = { [weak self] presentationLayout, transition in self?.gridPresentationLayoutUpdated(presentationLayout, transition: transition) @@ -286,6 +291,10 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode { self.contentGridNode.transaction(GridNodeTransaction(deleteItems: transition.deletions, insertItems: transition.insertions, updateItems: transition.updates, scrollToItem: nil, updateLayout: nil, itemTransition: itemTransition, stationaryItems: .none, updateFirstIndexInSectionOffset: nil), completion: { _ in }) } } + + func setDidBeginDragging(_ f: (() -> Void)?) { + self.contentDidBeginDragging = f + } func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f @@ -458,8 +467,6 @@ final class ShareTopicsContainerNode: ASDisplayNode, ShareContentContainerNode { self.contentSubtitleNode.frame = originalSubtitleFrame transition.updateFrame(node: self.contentSubtitleNode, frame: subtitleFrame) - - self.contentOffsetUpdated?(presentationLayout.contentOffset.y, actualTransition) } } diff --git a/submodules/TelegramApi/Sources/Api0.swift b/submodules/TelegramApi/Sources/Api0.swift index 1a147326a5..472254e753 100644 --- a/submodules/TelegramApi/Sources/Api0.swift +++ b/submodules/TelegramApi/Sources/Api0.swift @@ -6,6 +6,7 @@ public enum Api { public enum channels {} public enum chatlists {} public enum contacts {} + public enum fragment {} public enum help {} public enum messages {} public enum payments {} @@ -28,6 +29,7 @@ public enum Api { public enum chatlists {} public enum contacts {} public enum folders {} + public enum fragment {} public enum help {} public enum langpack {} public enum messages {} @@ -321,6 +323,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1736378792] = { return Api.InputCheckPasswordSRP.parse_inputCheckPasswordEmpty($0) } dict[-763367294] = { return Api.InputCheckPasswordSRP.parse_inputCheckPasswordSRP($0) } dict[1968737087] = { return Api.InputClientProxy.parse_inputClientProxy($0) } + dict[-1562241884] = { return Api.InputCollectible.parse_inputCollectiblePhone($0) } + dict[-476815191] = { return Api.InputCollectible.parse_inputCollectibleUsername($0) } dict[-208488460] = { return Api.InputContact.parse_inputPhoneContact($0) } dict[-55902537] = { return Api.InputDialogPeer.parse_inputDialogPeer($0) } dict[1684014375] = { return Api.InputDialogPeer.parse_inputDialogPeerFolder($0) } @@ -491,7 +495,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[340088945] = { return Api.MediaArea.parse_mediaAreaSuggestedReaction($0) } dict[-1098720356] = { return Api.MediaArea.parse_mediaAreaVenue($0) } dict[64088654] = { return Api.MediaAreaCoordinates.parse_mediaAreaCoordinates($0) } - dict[-1502839044] = { return Api.Message.parse_message($0) } + dict[556221267] = { return Api.Message.parse_message($0) } dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) } dict[721967202] = { return Api.Message.parse_messageService($0) } dict[-872240531] = { return Api.MessageAction.parse_messageActionBoostApply($0) } @@ -1125,6 +1129,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[1891070632] = { return Api.contacts.TopPeers.parse_topPeers($0) } dict[-1255369827] = { return Api.contacts.TopPeers.parse_topPeersDisabled($0) } dict[-567906571] = { return Api.contacts.TopPeers.parse_topPeersNotModified($0) } + dict[1857945489] = { return Api.fragment.CollectibleInfo.parse_collectibleInfo($0) } dict[-585598930] = { return Api.help.AppConfig.parse_appConfig($0) } dict[2094949405] = { return Api.help.AppConfig.parse_appConfigNotModified($0) } dict[-860107216] = { return Api.help.AppUpdate.parse_appUpdate($0) } @@ -1203,6 +1208,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = { dict[-1938715001] = { return Api.messages.Messages.parse_messages($0) } dict[1951620897] = { return Api.messages.Messages.parse_messagesNotModified($0) } dict[978610270] = { return Api.messages.Messages.parse_messagesSlice($0) } + dict[-83926371] = { return Api.messages.MyStickers.parse_myStickers($0) } dict[863093588] = { return Api.messages.PeerDialogs.parse_peerDialogs($0) } dict[1753266509] = { return Api.messages.PeerSettings.parse_peerSettings($0) } dict[-963811691] = { return Api.messages.QuickReplies.parse_quickReplies($0) } @@ -1315,7 +1321,7 @@ public extension Api { return parser(reader) } else { - telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found") + telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found") return nil } } @@ -1587,6 +1593,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.InputClientProxy: _1.serialize(buffer, boxed) + case let _1 as Api.InputCollectible: + _1.serialize(buffer, boxed) case let _1 as Api.InputContact: _1.serialize(buffer, boxed) case let _1 as Api.InputDialogPeer: @@ -2043,6 +2051,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.contacts.TopPeers: _1.serialize(buffer, boxed) + case let _1 as Api.fragment.CollectibleInfo: + _1.serialize(buffer, boxed) case let _1 as Api.help.AppConfig: _1.serialize(buffer, boxed) case let _1 as Api.help.AppUpdate: @@ -2149,6 +2159,8 @@ public extension Api { _1.serialize(buffer, boxed) case let _1 as Api.messages.Messages: _1.serialize(buffer, boxed) + case let _1 as Api.messages.MyStickers: + _1.serialize(buffer, boxed) case let _1 as Api.messages.PeerDialogs: _1.serialize(buffer, boxed) case let _1 as Api.messages.PeerSettings: diff --git a/submodules/TelegramApi/Sources/Api10.swift b/submodules/TelegramApi/Sources/Api10.swift index 4fe4c26f44..2148237347 100644 --- a/submodules/TelegramApi/Sources/Api10.swift +++ b/submodules/TelegramApi/Sources/Api10.swift @@ -1,3 +1,183 @@ +public extension Api { + enum InputPrivacyRule: TypeConstructorDescription { + case inputPrivacyValueAllowAll + case inputPrivacyValueAllowChatParticipants(chats: [Int64]) + case inputPrivacyValueAllowCloseFriends + 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 .inputPrivacyValueAllowCloseFriends: + if boxed { + buffer.appendInt32(793067081) + } + + 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", chats as Any)]) + case .inputPrivacyValueAllowCloseFriends: + return ("inputPrivacyValueAllowCloseFriends", []) + case .inputPrivacyValueAllowContacts: + return ("inputPrivacyValueAllowContacts", []) + case .inputPrivacyValueAllowUsers(let users): + return ("inputPrivacyValueAllowUsers", [("users", users as Any)]) + case .inputPrivacyValueDisallowAll: + return ("inputPrivacyValueDisallowAll", []) + case .inputPrivacyValueDisallowChatParticipants(let chats): + return ("inputPrivacyValueDisallowChatParticipants", [("chats", chats as Any)]) + case .inputPrivacyValueDisallowContacts: + return ("inputPrivacyValueDisallowContacts", []) + case .inputPrivacyValueDisallowUsers(let users): + return ("inputPrivacyValueDisallowUsers", [("users", users as Any)]) + } + } + + 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_inputPrivacyValueAllowCloseFriends(_ reader: BufferReader) -> InputPrivacyRule? { + return Api.InputPrivacyRule.inputPrivacyValueAllowCloseFriends + } + 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 InputQuickReplyShortcut: TypeConstructorDescription { case inputQuickReplyShortcut(shortcut: String) @@ -844,229 +1024,3 @@ public extension Api { } } -public extension Api { - enum InputTheme: TypeConstructorDescription { - case inputTheme(id: Int64, accessHash: Int64) - case inputThemeSlug(slug: String) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputTheme(let id, let accessHash): - if boxed { - buffer.appendInt32(1012306921) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - break - case .inputThemeSlug(let slug): - if boxed { - buffer.appendInt32(-175567375) - } - serializeString(slug, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputTheme(let id, let accessHash): - return ("inputTheme", [("id", id as Any), ("accessHash", accessHash as Any)]) - case .inputThemeSlug(let slug): - return ("inputThemeSlug", [("slug", slug as Any)]) - } - } - - public static func parse_inputTheme(_ reader: BufferReader) -> InputTheme? { - 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.InputTheme.inputTheme(id: _1!, accessHash: _2!) - } - else { - return nil - } - } - public static func parse_inputThemeSlug(_ reader: BufferReader) -> InputTheme? { - var _1: String? - _1 = parseString(reader) - let _c1 = _1 != nil - if _c1 { - return Api.InputTheme.inputThemeSlug(slug: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - enum InputThemeSettings: TypeConstructorDescription { - case inputThemeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, outboxAccentColor: Int32?, messageColors: [Int32]?, wallpaper: Api.InputWallPaper?, wallpaperSettings: Api.WallPaperSettings?) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings): - if boxed { - buffer.appendInt32(-1881255857) - } - serializeInt32(flags, buffer: buffer, boxed: false) - baseTheme.serialize(buffer, true) - serializeInt32(accentColor, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 3) != 0 {serializeInt32(outboxAccentColor!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(messageColors!.count)) - for item in messageColors! { - serializeInt32(item, buffer: buffer, boxed: false) - }} - if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {wallpaperSettings!.serialize(buffer, true)} - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings): - return ("inputThemeSettings", [("flags", flags as Any), ("baseTheme", baseTheme as Any), ("accentColor", accentColor as Any), ("outboxAccentColor", outboxAccentColor as Any), ("messageColors", messageColors as Any), ("wallpaper", wallpaper as Any), ("wallpaperSettings", wallpaperSettings as Any)]) - } - } - - public static func parse_inputThemeSettings(_ reader: BufferReader) -> InputThemeSettings? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.BaseTheme? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.BaseTheme - } - var _3: Int32? - _3 = reader.readInt32() - var _4: Int32? - if Int(_1!) & Int(1 << 3) != 0 {_4 = reader.readInt32() } - var _5: [Int32]? - if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) - } } - var _6: Api.InputWallPaper? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.InputWallPaper - } } - var _7: Api.WallPaperSettings? - if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings - } } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil - let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil - let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { - return Api.InputThemeSettings.inputThemeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, outboxAccentColor: _4, messageColors: _5, wallpaper: _6, wallpaperSettings: _7) - } - else { - return nil - } - } - - } -} -public extension Api { - indirect enum InputUser: TypeConstructorDescription { - case inputUser(userId: Int64, accessHash: Int64) - case inputUserEmpty - case inputUserFromMessage(peer: Api.InputPeer, msgId: Int32, userId: Int64) - case inputUserSelf - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputUser(let userId, let accessHash): - if boxed { - buffer.appendInt32(-233744186) - } - serializeInt64(userId, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - break - case .inputUserEmpty: - if boxed { - buffer.appendInt32(-1182234929) - } - - break - case .inputUserFromMessage(let peer, let msgId, let userId): - if boxed { - buffer.appendInt32(497305826) - } - peer.serialize(buffer, true) - serializeInt32(msgId, buffer: buffer, boxed: false) - serializeInt64(userId, buffer: buffer, boxed: false) - break - case .inputUserSelf: - if boxed { - buffer.appendInt32(-138301121) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputUser(let userId, let accessHash): - return ("inputUser", [("userId", userId as Any), ("accessHash", accessHash as Any)]) - case .inputUserEmpty: - return ("inputUserEmpty", []) - case .inputUserFromMessage(let peer, let msgId, let userId): - return ("inputUserFromMessage", [("peer", peer as Any), ("msgId", msgId as Any), ("userId", userId as Any)]) - case .inputUserSelf: - return ("inputUserSelf", []) - } - } - - public static func parse_inputUser(_ reader: BufferReader) -> InputUser? { - 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.InputUser.inputUser(userId: _1!, accessHash: _2!) - } - else { - return nil - } - } - public static func parse_inputUserEmpty(_ reader: BufferReader) -> InputUser? { - return Api.InputUser.inputUserEmpty - } - public static func parse_inputUserFromMessage(_ reader: BufferReader) -> InputUser? { - var _1: Api.InputPeer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputPeer - } - 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.InputUser.inputUserFromMessage(peer: _1!, msgId: _2!, userId: _3!) - } - else { - return nil - } - } - public static func parse_inputUserSelf(_ reader: BufferReader) -> InputUser? { - return Api.InputUser.inputUserSelf - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api11.swift b/submodules/TelegramApi/Sources/Api11.swift index 89037ef849..024db526a7 100644 --- a/submodules/TelegramApi/Sources/Api11.swift +++ b/submodules/TelegramApi/Sources/Api11.swift @@ -1,3 +1,229 @@ +public extension Api { + enum InputTheme: TypeConstructorDescription { + case inputTheme(id: Int64, accessHash: Int64) + case inputThemeSlug(slug: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputTheme(let id, let accessHash): + if boxed { + buffer.appendInt32(1012306921) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + break + case .inputThemeSlug(let slug): + if boxed { + buffer.appendInt32(-175567375) + } + serializeString(slug, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputTheme(let id, let accessHash): + return ("inputTheme", [("id", id as Any), ("accessHash", accessHash as Any)]) + case .inputThemeSlug(let slug): + return ("inputThemeSlug", [("slug", slug as Any)]) + } + } + + public static func parse_inputTheme(_ reader: BufferReader) -> InputTheme? { + 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.InputTheme.inputTheme(id: _1!, accessHash: _2!) + } + else { + return nil + } + } + public static func parse_inputThemeSlug(_ reader: BufferReader) -> InputTheme? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.InputTheme.inputThemeSlug(slug: _1!) + } + else { + return nil + } + } + + } +} +public extension Api { + enum InputThemeSettings: TypeConstructorDescription { + case inputThemeSettings(flags: Int32, baseTheme: Api.BaseTheme, accentColor: Int32, outboxAccentColor: Int32?, messageColors: [Int32]?, wallpaper: Api.InputWallPaper?, wallpaperSettings: Api.WallPaperSettings?) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings): + if boxed { + buffer.appendInt32(-1881255857) + } + serializeInt32(flags, buffer: buffer, boxed: false) + baseTheme.serialize(buffer, true) + serializeInt32(accentColor, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 3) != 0 {serializeInt32(outboxAccentColor!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(messageColors!.count)) + for item in messageColors! { + serializeInt32(item, buffer: buffer, boxed: false) + }} + if Int(flags) & Int(1 << 1) != 0 {wallpaper!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {wallpaperSettings!.serialize(buffer, true)} + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputThemeSettings(let flags, let baseTheme, let accentColor, let outboxAccentColor, let messageColors, let wallpaper, let wallpaperSettings): + return ("inputThemeSettings", [("flags", flags as Any), ("baseTheme", baseTheme as Any), ("accentColor", accentColor as Any), ("outboxAccentColor", outboxAccentColor as Any), ("messageColors", messageColors as Any), ("wallpaper", wallpaper as Any), ("wallpaperSettings", wallpaperSettings as Any)]) + } + } + + public static func parse_inputThemeSettings(_ reader: BufferReader) -> InputThemeSettings? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.BaseTheme? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.BaseTheme + } + var _3: Int32? + _3 = reader.readInt32() + var _4: Int32? + if Int(_1!) & Int(1 << 3) != 0 {_4 = reader.readInt32() } + var _5: [Int32]? + if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: -1471112230, elementType: Int32.self) + } } + var _6: Api.InputWallPaper? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.InputWallPaper + } } + var _7: Api.WallPaperSettings? + if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.WallPaperSettings + } } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 3) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil + let _c6 = (Int(_1!) & Int(1 << 1) == 0) || _6 != nil + let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 { + return Api.InputThemeSettings.inputThemeSettings(flags: _1!, baseTheme: _2!, accentColor: _3!, outboxAccentColor: _4, messageColors: _5, wallpaper: _6, wallpaperSettings: _7) + } + else { + return nil + } + } + + } +} +public extension Api { + indirect enum InputUser: TypeConstructorDescription { + case inputUser(userId: Int64, accessHash: Int64) + case inputUserEmpty + case inputUserFromMessage(peer: Api.InputPeer, msgId: Int32, userId: Int64) + case inputUserSelf + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputUser(let userId, let accessHash): + if boxed { + buffer.appendInt32(-233744186) + } + serializeInt64(userId, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + break + case .inputUserEmpty: + if boxed { + buffer.appendInt32(-1182234929) + } + + break + case .inputUserFromMessage(let peer, let msgId, let userId): + if boxed { + buffer.appendInt32(497305826) + } + peer.serialize(buffer, true) + serializeInt32(msgId, buffer: buffer, boxed: false) + serializeInt64(userId, buffer: buffer, boxed: false) + break + case .inputUserSelf: + if boxed { + buffer.appendInt32(-138301121) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputUser(let userId, let accessHash): + return ("inputUser", [("userId", userId as Any), ("accessHash", accessHash as Any)]) + case .inputUserEmpty: + return ("inputUserEmpty", []) + case .inputUserFromMessage(let peer, let msgId, let userId): + return ("inputUserFromMessage", [("peer", peer as Any), ("msgId", msgId as Any), ("userId", userId as Any)]) + case .inputUserSelf: + return ("inputUserSelf", []) + } + } + + public static func parse_inputUser(_ reader: BufferReader) -> InputUser? { + 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.InputUser.inputUser(userId: _1!, accessHash: _2!) + } + else { + return nil + } + } + public static func parse_inputUserEmpty(_ reader: BufferReader) -> InputUser? { + return Api.InputUser.inputUserEmpty + } + public static func parse_inputUserFromMessage(_ reader: BufferReader) -> InputUser? { + var _1: Api.InputPeer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputPeer + } + 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.InputUser.inputUserFromMessage(peer: _1!, msgId: _2!, userId: _3!) + } + else { + return nil + } + } + public static func parse_inputUserSelf(_ reader: BufferReader) -> InputUser? { + return Api.InputUser.inputUserSelf + } + + } +} public extension Api { enum InputWallPaper: TypeConstructorDescription { case inputWallPaper(id: Int64, accessHash: Int64) @@ -942,45 +1168,3 @@ public extension Api { } } -public extension Api { - enum KeyboardButtonRow: TypeConstructorDescription { - case keyboardButtonRow(buttons: [Api.KeyboardButton]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .keyboardButtonRow(let buttons): - if boxed { - buffer.appendInt32(2002815875) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(buttons.count)) - for item in buttons { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .keyboardButtonRow(let buttons): - return ("keyboardButtonRow", [("buttons", buttons as Any)]) - } - } - - public static func parse_keyboardButtonRow(_ reader: BufferReader) -> KeyboardButtonRow? { - var _1: [Api.KeyboardButton]? - if let _ = reader.readInt32() { - _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.KeyboardButton.self) - } - let _c1 = _1 != nil - if _c1 { - return Api.KeyboardButtonRow.keyboardButtonRow(buttons: _1!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api12.swift b/submodules/TelegramApi/Sources/Api12.swift index 1edeff5668..ca1f24d375 100644 --- a/submodules/TelegramApi/Sources/Api12.swift +++ b/submodules/TelegramApi/Sources/Api12.swift @@ -1,3 +1,45 @@ +public extension Api { + enum KeyboardButtonRow: TypeConstructorDescription { + case keyboardButtonRow(buttons: [Api.KeyboardButton]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .keyboardButtonRow(let buttons): + if boxed { + buffer.appendInt32(2002815875) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(buttons.count)) + for item in buttons { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .keyboardButtonRow(let buttons): + return ("keyboardButtonRow", [("buttons", buttons as Any)]) + } + } + + public static func parse_keyboardButtonRow(_ reader: BufferReader) -> KeyboardButtonRow? { + var _1: [Api.KeyboardButton]? + if let _ = reader.readInt32() { + _1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.KeyboardButton.self) + } + let _c1 = _1 != nil + if _c1 { + return Api.KeyboardButtonRow.keyboardButtonRow(buttons: _1!) + } + else { + return nil + } + } + + } +} public extension Api { enum LabeledPrice: TypeConstructorDescription { case labeledPrice(label: String, amount: Int64) @@ -586,17 +628,18 @@ public extension Api { } public extension Api { indirect enum Message: TypeConstructorDescription { - case message(flags: Int32, id: Int32, fromId: Api.Peer?, fromBoostsApplied: Int32?, peerId: Api.Peer, savedPeerId: 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?, quickReplyShortcutId: Int32?) + case message(flags: Int32, flags2: Int32, id: Int32, fromId: Api.Peer?, fromBoostsApplied: Int32?, peerId: Api.Peer, savedPeerId: 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?, quickReplyShortcutId: 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 fromBoostsApplied, let peerId, let savedPeerId, 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, let quickReplyShortcutId): + case .message(let flags, let flags2, let id, let fromId, let fromBoostsApplied, let peerId, let savedPeerId, 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, let quickReplyShortcutId): if boxed { - buffer.appendInt32(-1502839044) + buffer.appendInt32(556221267) } serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt32(flags2, buffer: buffer, boxed: false) serializeInt32(id, buffer: buffer, boxed: false) if Int(flags) & Int(1 << 8) != 0 {fromId!.serialize(buffer, true)} if Int(flags) & Int(1 << 29) != 0 {serializeInt32(fromBoostsApplied!, buffer: buffer, boxed: false)} @@ -655,8 +698,8 @@ public extension Api { public func descriptionFields() -> (String, [(String, Any)]) { switch self { - case .message(let flags, let id, let fromId, let fromBoostsApplied, let peerId, let savedPeerId, 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, let quickReplyShortcutId): - return ("message", [("flags", flags as Any), ("id", id as Any), ("fromId", fromId as Any), ("fromBoostsApplied", fromBoostsApplied as Any), ("peerId", peerId as Any), ("savedPeerId", savedPeerId as Any), ("fwdFrom", fwdFrom as Any), ("viaBotId", viaBotId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("message", message as Any), ("media", media as Any), ("replyMarkup", replyMarkup as Any), ("entities", entities as Any), ("views", views as Any), ("forwards", forwards as Any), ("replies", replies as Any), ("editDate", editDate as Any), ("postAuthor", postAuthor as Any), ("groupedId", groupedId as Any), ("reactions", reactions as Any), ("restrictionReason", restrictionReason as Any), ("ttlPeriod", ttlPeriod as Any), ("quickReplyShortcutId", quickReplyShortcutId as Any)]) + case .message(let flags, let flags2, let id, let fromId, let fromBoostsApplied, let peerId, let savedPeerId, 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, let quickReplyShortcutId): + return ("message", [("flags", flags as Any), ("flags2", flags2 as Any), ("id", id as Any), ("fromId", fromId as Any), ("fromBoostsApplied", fromBoostsApplied as Any), ("peerId", peerId as Any), ("savedPeerId", savedPeerId as Any), ("fwdFrom", fwdFrom as Any), ("viaBotId", viaBotId as Any), ("replyTo", replyTo as Any), ("date", date as Any), ("message", message as Any), ("media", media as Any), ("replyMarkup", replyMarkup as Any), ("entities", entities as Any), ("views", views as Any), ("forwards", forwards as Any), ("replies", replies as Any), ("editDate", editDate as Any), ("postAuthor", postAuthor as Any), ("groupedId", groupedId as Any), ("reactions", reactions as Any), ("restrictionReason", restrictionReason as Any), ("ttlPeriod", ttlPeriod as Any), ("quickReplyShortcutId", quickReplyShortcutId as Any)]) case .messageEmpty(let flags, let id, let peerId): return ("messageEmpty", [("flags", flags as Any), ("id", id as Any), ("peerId", peerId as Any)]) case .messageService(let flags, let id, let fromId, let peerId, let replyTo, let date, let action, let ttlPeriod): @@ -669,98 +712,101 @@ public extension Api { _1 = reader.readInt32() var _2: Int32? _2 = reader.readInt32() - var _3: Api.Peer? + var _3: Int32? + _3 = reader.readInt32() + var _4: Api.Peer? if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() { - _3 = Api.parse(reader, signature: signature) as? Api.Peer + _4 = Api.parse(reader, signature: signature) as? Api.Peer } } - var _4: Int32? - if Int(_1!) & Int(1 << 29) != 0 {_4 = reader.readInt32() } - var _5: Api.Peer? - if let signature = reader.readInt32() { - _5 = Api.parse(reader, signature: signature) as? Api.Peer - } + var _5: Int32? + if Int(_1!) & Int(1 << 29) != 0 {_5 = reader.readInt32() } var _6: Api.Peer? - if Int(_1!) & Int(1 << 28) != 0 {if let signature = reader.readInt32() { + if let signature = reader.readInt32() { _6 = Api.parse(reader, signature: signature) as? Api.Peer + } + var _7: Api.Peer? + if Int(_1!) & Int(1 << 28) != 0 {if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.Peer } } - var _7: Api.MessageFwdHeader? + var _8: Api.MessageFwdHeader? if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader + _8 = Api.parse(reader, signature: signature) as? Api.MessageFwdHeader } } - var _8: Int64? - if Int(_1!) & Int(1 << 11) != 0 {_8 = reader.readInt64() } - var _9: Api.MessageReplyHeader? + 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() { - _9 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader + _10 = Api.parse(reader, signature: signature) as? Api.MessageReplyHeader } } - var _10: Int32? - _10 = reader.readInt32() - var _11: String? - _11 = parseString(reader) - var _12: Api.MessageMedia? + var _11: Int32? + _11 = reader.readInt32() + var _12: String? + _12 = parseString(reader) + var _13: Api.MessageMedia? if Int(_1!) & Int(1 << 9) != 0 {if let signature = reader.readInt32() { - _12 = Api.parse(reader, signature: signature) as? Api.MessageMedia + _13 = Api.parse(reader, signature: signature) as? Api.MessageMedia } } - var _13: Api.ReplyMarkup? + var _14: Api.ReplyMarkup? if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() { - _13 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup + _14 = Api.parse(reader, signature: signature) as? Api.ReplyMarkup } } - var _14: [Api.MessageEntity]? + var _15: [Api.MessageEntity]? if Int(_1!) & Int(1 << 7) != 0 {if let _ = reader.readInt32() { - _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) + _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self) } } - var _15: Int32? - if Int(_1!) & Int(1 << 10) != 0 {_15 = reader.readInt32() } var _16: Int32? if Int(_1!) & Int(1 << 10) != 0 {_16 = reader.readInt32() } - var _17: Api.MessageReplies? + var _17: Int32? + if Int(_1!) & Int(1 << 10) != 0 {_17 = reader.readInt32() } + var _18: Api.MessageReplies? if Int(_1!) & Int(1 << 23) != 0 {if let signature = reader.readInt32() { - _17 = Api.parse(reader, signature: signature) as? Api.MessageReplies + _18 = Api.parse(reader, signature: signature) as? Api.MessageReplies } } - var _18: Int32? - if Int(_1!) & Int(1 << 15) != 0 {_18 = reader.readInt32() } - var _19: String? - if Int(_1!) & Int(1 << 16) != 0 {_19 = parseString(reader) } - var _20: Int64? - if Int(_1!) & Int(1 << 17) != 0 {_20 = reader.readInt64() } - var _21: Api.MessageReactions? + var _19: Int32? + if Int(_1!) & Int(1 << 15) != 0 {_19 = reader.readInt32() } + var _20: String? + if Int(_1!) & Int(1 << 16) != 0 {_20 = parseString(reader) } + var _21: Int64? + if Int(_1!) & Int(1 << 17) != 0 {_21 = reader.readInt64() } + var _22: Api.MessageReactions? if Int(_1!) & Int(1 << 20) != 0 {if let signature = reader.readInt32() { - _21 = Api.parse(reader, signature: signature) as? Api.MessageReactions + _22 = Api.parse(reader, signature: signature) as? Api.MessageReactions } } - var _22: [Api.RestrictionReason]? + var _23: [Api.RestrictionReason]? if Int(_1!) & Int(1 << 22) != 0 {if let _ = reader.readInt32() { - _22 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) + _23 = Api.parseVector(reader, elementSignature: 0, elementType: Api.RestrictionReason.self) } } - var _23: Int32? - if Int(_1!) & Int(1 << 25) != 0 {_23 = reader.readInt32() } var _24: Int32? - if Int(_1!) & Int(1 << 30) != 0 {_24 = reader.readInt32() } + if Int(_1!) & Int(1 << 25) != 0 {_24 = reader.readInt32() } + var _25: Int32? + if Int(_1!) & Int(1 << 30) != 0 {_25 = reader.readInt32() } let _c1 = _1 != nil let _c2 = _2 != nil - let _c3 = (Int(_1!) & Int(1 << 8) == 0) || _3 != nil - let _c4 = (Int(_1!) & Int(1 << 29) == 0) || _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 28) == 0) || _6 != nil - let _c7 = (Int(_1!) & Int(1 << 2) == 0) || _7 != nil - let _c8 = (Int(_1!) & Int(1 << 11) == 0) || _8 != nil - let _c9 = (Int(_1!) & Int(1 << 3) == 0) || _9 != nil - let _c10 = _10 != nil + let _c3 = _3 != nil + let _c4 = (Int(_1!) & Int(1 << 8) == 0) || _4 != nil + let _c5 = (Int(_1!) & Int(1 << 29) == 0) || _5 != nil + let _c6 = _6 != nil + let _c7 = (Int(_1!) & Int(1 << 28) == 0) || _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 = _11 != nil - let _c12 = (Int(_1!) & Int(1 << 9) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 6) == 0) || _13 != nil - let _c14 = (Int(_1!) & Int(1 << 7) == 0) || _14 != nil - let _c15 = (Int(_1!) & Int(1 << 10) == 0) || _15 != nil + let _c12 = _12 != nil + let _c13 = (Int(_1!) & Int(1 << 9) == 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 << 10) == 0) || _16 != nil - let _c17 = (Int(_1!) & Int(1 << 23) == 0) || _17 != nil - let _c18 = (Int(_1!) & Int(1 << 15) == 0) || _18 != nil - let _c19 = (Int(_1!) & Int(1 << 16) == 0) || _19 != nil - let _c20 = (Int(_1!) & Int(1 << 17) == 0) || _20 != nil - let _c21 = (Int(_1!) & Int(1 << 20) == 0) || _21 != nil - let _c22 = (Int(_1!) & Int(1 << 22) == 0) || _22 != nil - let _c23 = (Int(_1!) & Int(1 << 25) == 0) || _23 != nil - let _c24 = (Int(_1!) & Int(1 << 30) == 0) || _24 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 { - return Api.Message.message(flags: _1!, id: _2!, fromId: _3, fromBoostsApplied: _4, peerId: _5!, savedPeerId: _6, fwdFrom: _7, viaBotId: _8, replyTo: _9, date: _10!, message: _11!, media: _12, replyMarkup: _13, entities: _14, views: _15, forwards: _16, replies: _17, editDate: _18, postAuthor: _19, groupedId: _20, reactions: _21, restrictionReason: _22, ttlPeriod: _23, quickReplyShortcutId: _24) + let _c17 = (Int(_1!) & Int(1 << 10) == 0) || _17 != nil + let _c18 = (Int(_1!) & Int(1 << 23) == 0) || _18 != nil + let _c19 = (Int(_1!) & Int(1 << 15) == 0) || _19 != nil + let _c20 = (Int(_1!) & Int(1 << 16) == 0) || _20 != nil + let _c21 = (Int(_1!) & Int(1 << 17) == 0) || _21 != nil + let _c22 = (Int(_1!) & Int(1 << 20) == 0) || _22 != nil + let _c23 = (Int(_1!) & Int(1 << 22) == 0) || _23 != nil + let _c24 = (Int(_1!) & Int(1 << 25) == 0) || _24 != nil + let _c25 = (Int(_1!) & Int(1 << 30) == 0) || _25 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 { + return Api.Message.message(flags: _1!, flags2: _2!, id: _3!, fromId: _4, fromBoostsApplied: _5, peerId: _6!, savedPeerId: _7, fwdFrom: _8, viaBotId: _9, replyTo: _10, date: _11!, message: _12!, media: _13, replyMarkup: _14, entities: _15, views: _16, forwards: _17, replies: _18, editDate: _19, postAuthor: _20, groupedId: _21, reactions: _22, restrictionReason: _23, ttlPeriod: _24, quickReplyShortcutId: _25) } else { return nil diff --git a/submodules/TelegramApi/Sources/Api26.swift b/submodules/TelegramApi/Sources/Api26.swift index e688ea037b..6967f4eb80 100644 --- a/submodules/TelegramApi/Sources/Api26.swift +++ b/submodules/TelegramApi/Sources/Api26.swift @@ -634,6 +634,62 @@ public extension Api.contacts { } } +public extension Api.fragment { + enum CollectibleInfo: TypeConstructorDescription { + case collectibleInfo(purchaseDate: Int32, currency: String, amount: Int64, cryptoCurrency: String, cryptoAmount: Int64, url: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .collectibleInfo(let purchaseDate, let currency, let amount, let cryptoCurrency, let cryptoAmount, let url): + if boxed { + buffer.appendInt32(1857945489) + } + serializeInt32(purchaseDate, buffer: buffer, boxed: false) + serializeString(currency, buffer: buffer, boxed: false) + serializeInt64(amount, buffer: buffer, boxed: false) + serializeString(cryptoCurrency, buffer: buffer, boxed: false) + serializeInt64(cryptoAmount, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .collectibleInfo(let purchaseDate, let currency, let amount, let cryptoCurrency, let cryptoAmount, let url): + return ("collectibleInfo", [("purchaseDate", purchaseDate as Any), ("currency", currency as Any), ("amount", amount as Any), ("cryptoCurrency", cryptoCurrency as Any), ("cryptoAmount", cryptoAmount as Any), ("url", url as Any)]) + } + } + + public static func parse_collectibleInfo(_ reader: BufferReader) -> CollectibleInfo? { + var _1: Int32? + _1 = reader.readInt32() + var _2: String? + _2 = parseString(reader) + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + _4 = parseString(reader) + var _5: Int64? + _5 = reader.readInt64() + 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.fragment.CollectibleInfo.collectibleInfo(purchaseDate: _1!, currency: _2!, amount: _3!, cryptoCurrency: _4!, cryptoAmount: _5!, url: _6!) + } + else { + return nil + } + } + + } +} public extension Api.help { enum AppConfig: TypeConstructorDescription { case appConfig(hash: Int32, config: Api.JSONValue) @@ -1308,89 +1364,3 @@ public extension Api.help { } } -public extension Api.help { - enum PremiumPromo: TypeConstructorDescription { - case premiumPromo(statusText: String, statusEntities: [Api.MessageEntity], videoSections: [String], videos: [Api.Document], periodOptions: [Api.PremiumSubscriptionOption], users: [Api.User]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let periodOptions, let users): - if boxed { - buffer.appendInt32(1395946908) - } - 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) - } - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(periodOptions.count)) - for item in periodOptions { - 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 .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let periodOptions, let users): - return ("premiumPromo", [("statusText", statusText as Any), ("statusEntities", statusEntities as Any), ("videoSections", videoSections as Any), ("videos", videos as Any), ("periodOptions", periodOptions as Any), ("users", users as Any)]) - } - } - - public static func parse_premiumPromo(_ reader: BufferReader) -> PremiumPromo? { - 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]? - 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: [Api.PremiumSubscriptionOption]? - if let _ = reader.readInt32() { - _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PremiumSubscriptionOption.self) - } - var _6: [Api.User]? - if let _ = reader.readInt32() { - _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = _6 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { - return Api.help.PremiumPromo.premiumPromo(statusText: _1!, statusEntities: _2!, videoSections: _3!, videos: _4!, periodOptions: _5!, users: _6!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api27.swift b/submodules/TelegramApi/Sources/Api27.swift index 5069e6504e..91159e86a9 100644 --- a/submodules/TelegramApi/Sources/Api27.swift +++ b/submodules/TelegramApi/Sources/Api27.swift @@ -1,3 +1,89 @@ +public extension Api.help { + enum PremiumPromo: TypeConstructorDescription { + case premiumPromo(statusText: String, statusEntities: [Api.MessageEntity], videoSections: [String], videos: [Api.Document], periodOptions: [Api.PremiumSubscriptionOption], users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let periodOptions, let users): + if boxed { + buffer.appendInt32(1395946908) + } + 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) + } + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(periodOptions.count)) + for item in periodOptions { + 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 .premiumPromo(let statusText, let statusEntities, let videoSections, let videos, let periodOptions, let users): + return ("premiumPromo", [("statusText", statusText as Any), ("statusEntities", statusEntities as Any), ("videoSections", videoSections as Any), ("videos", videos as Any), ("periodOptions", periodOptions as Any), ("users", users as Any)]) + } + } + + public static func parse_premiumPromo(_ reader: BufferReader) -> PremiumPromo? { + 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]? + 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: [Api.PremiumSubscriptionOption]? + if let _ = reader.readInt32() { + _5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PremiumSubscriptionOption.self) + } + var _6: [Api.User]? + if let _ = reader.readInt32() { + _6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = _6 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 { + return Api.help.PremiumPromo.premiumPromo(statusText: _1!, statusEntities: _2!, videoSections: _3!, videos: _4!, periodOptions: _5!, users: _6!) + } + else { + return nil + } + } + + } +} 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?) @@ -1290,49 +1376,3 @@ public extension Api.messages { } } -public extension Api.messages { - enum DialogFilters: TypeConstructorDescription { - case dialogFilters(flags: Int32, filters: [Api.DialogFilter]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .dialogFilters(let flags, let filters): - if boxed { - buffer.appendInt32(718878489) - } - serializeInt32(flags, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(filters.count)) - for item in filters { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .dialogFilters(let flags, let filters): - return ("dialogFilters", [("flags", flags as Any), ("filters", filters as Any)]) - } - } - - public static func parse_dialogFilters(_ reader: BufferReader) -> DialogFilters? { - var _1: Int32? - _1 = reader.readInt32() - var _2: [Api.DialogFilter]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogFilter.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.DialogFilters.dialogFilters(flags: _1!, filters: _2!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api28.swift b/submodules/TelegramApi/Sources/Api28.swift index cb218918b1..df72f59ee8 100644 --- a/submodules/TelegramApi/Sources/Api28.swift +++ b/submodules/TelegramApi/Sources/Api28.swift @@ -1,3 +1,49 @@ +public extension Api.messages { + enum DialogFilters: TypeConstructorDescription { + case dialogFilters(flags: Int32, filters: [Api.DialogFilter]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .dialogFilters(let flags, let filters): + if boxed { + buffer.appendInt32(718878489) + } + serializeInt32(flags, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(filters.count)) + for item in filters { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .dialogFilters(let flags, let filters): + return ("dialogFilters", [("flags", flags as Any), ("filters", filters as Any)]) + } + } + + public static func parse_dialogFilters(_ reader: BufferReader) -> DialogFilters? { + var _1: Int32? + _1 = reader.readInt32() + var _2: [Api.DialogFilter]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DialogFilter.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.DialogFilters.dialogFilters(flags: _1!, filters: _2!) + } + else { + return nil + } + } + + } +} public extension Api.messages { enum Dialogs: TypeConstructorDescription { case dialogs(dialogs: [Api.Dialog], messages: [Api.Message], chats: [Api.Chat], users: [Api.User]) @@ -1304,6 +1350,52 @@ public extension Api.messages { } } +public extension Api.messages { + enum MyStickers: TypeConstructorDescription { + case myStickers(count: Int32, sets: [Api.StickerSetCovered]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .myStickers(let count, let sets): + if boxed { + buffer.appendInt32(-83926371) + } + 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 .myStickers(let count, let sets): + return ("myStickers", [("count", count as Any), ("sets", sets as Any)]) + } + } + + public static func parse_myStickers(_ reader: BufferReader) -> MyStickers? { + 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.MyStickers.myStickers(count: _1!, sets: _2!) + } + else { + return nil + } + } + + } +} 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) @@ -1524,61 +1616,3 @@ public extension Api.messages { } } -public extension Api.messages { - enum Reactions: TypeConstructorDescription { - case reactions(hash: Int64, reactions: [Api.Reaction]) - case reactionsNotModified - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .reactions(let hash, let reactions): - if boxed { - buffer.appendInt32(-352454890) - } - serializeInt64(hash, buffer: buffer, boxed: false) - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(reactions.count)) - for item in reactions { - item.serialize(buffer, true) - } - break - case .reactionsNotModified: - if boxed { - buffer.appendInt32(-1334846497) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .reactions(let hash, let reactions): - return ("reactions", [("hash", hash as Any), ("reactions", reactions as Any)]) - case .reactionsNotModified: - return ("reactionsNotModified", []) - } - } - - public static func parse_reactions(_ reader: BufferReader) -> Reactions? { - var _1: Int64? - _1 = reader.readInt64() - var _2: [Api.Reaction]? - if let _ = reader.readInt32() { - _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Reaction.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.messages.Reactions.reactions(hash: _1!, reactions: _2!) - } - else { - return nil - } - } - public static func parse_reactionsNotModified(_ reader: BufferReader) -> Reactions? { - return Api.messages.Reactions.reactionsNotModified - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api29.swift b/submodules/TelegramApi/Sources/Api29.swift index fa6a398716..6e364e808a 100644 --- a/submodules/TelegramApi/Sources/Api29.swift +++ b/submodules/TelegramApi/Sources/Api29.swift @@ -1,3 +1,61 @@ +public extension Api.messages { + enum Reactions: TypeConstructorDescription { + case reactions(hash: Int64, reactions: [Api.Reaction]) + case reactionsNotModified + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .reactions(let hash, let reactions): + if boxed { + buffer.appendInt32(-352454890) + } + serializeInt64(hash, buffer: buffer, boxed: false) + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(reactions.count)) + for item in reactions { + item.serialize(buffer, true) + } + break + case .reactionsNotModified: + if boxed { + buffer.appendInt32(-1334846497) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .reactions(let hash, let reactions): + return ("reactions", [("hash", hash as Any), ("reactions", reactions as Any)]) + case .reactionsNotModified: + return ("reactionsNotModified", []) + } + } + + public static func parse_reactions(_ reader: BufferReader) -> Reactions? { + var _1: Int64? + _1 = reader.readInt64() + var _2: [Api.Reaction]? + if let _ = reader.readInt32() { + _2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.Reaction.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.messages.Reactions.reactions(hash: _1!, reactions: _2!) + } + else { + return nil + } + } + public static func parse_reactionsNotModified(_ reader: BufferReader) -> Reactions? { + return Api.messages.Reactions.reactionsNotModified + } + + } +} public extension Api.messages { enum RecentStickers: TypeConstructorDescription { case recentStickers(hash: Int64, packs: [Api.StickerPack], stickers: [Api.Document], dates: [Int32]) @@ -1346,121 +1404,3 @@ 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]) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users): - if boxed { - buffer.appendInt32(-1610250415) - } - serializeInt32(flags, buffer: buffer, boxed: false) - serializeInt64(formId, buffer: buffer, boxed: false) - serializeInt64(botId, buffer: buffer, boxed: false) - serializeString(title, buffer: buffer, boxed: false) - serializeString(description, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)} - invoice.serialize(buffer, true) - serializeInt64(providerId, buffer: buffer, boxed: false) - serializeString(url, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 4) != 0 {serializeString(nativeProvider!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 4) != 0 {nativeParams!.serialize(buffer, true)} - if Int(flags) & Int(1 << 6) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(additionalMethods!.count)) - for item in additionalMethods! { - item.serialize(buffer, true) - }} - if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)} - if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) - buffer.appendInt32(Int32(savedCredentials!.count)) - for item in savedCredentials! { - item.serialize(buffer, true) - }} - buffer.appendInt32(481674261) - buffer.appendInt32(Int32(users.count)) - for item in users { - item.serialize(buffer, true) - } - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users): - return ("paymentForm", [("flags", flags as Any), ("formId", formId as Any), ("botId", botId as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("providerId", providerId as Any), ("url", url as Any), ("nativeProvider", nativeProvider as Any), ("nativeParams", nativeParams as Any), ("additionalMethods", additionalMethods as Any), ("savedInfo", savedInfo as Any), ("savedCredentials", savedCredentials as Any), ("users", users as Any)]) - } - } - - public static func parse_paymentForm(_ reader: BufferReader) -> PaymentForm? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Int64? - _2 = reader.readInt64() - var _3: Int64? - _3 = reader.readInt64() - var _4: String? - _4 = parseString(reader) - var _5: String? - _5 = parseString(reader) - var _6: Api.WebDocument? - if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { - _6 = Api.parse(reader, signature: signature) as? Api.WebDocument - } } - var _7: Api.Invoice? - if let signature = reader.readInt32() { - _7 = Api.parse(reader, signature: signature) as? Api.Invoice - } - var _8: Int64? - _8 = reader.readInt64() - var _9: String? - _9 = parseString(reader) - var _10: String? - if Int(_1!) & Int(1 << 4) != 0 {_10 = parseString(reader) } - var _11: Api.DataJSON? - if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { - _11 = Api.parse(reader, signature: signature) as? Api.DataJSON - } } - var _12: [Api.PaymentFormMethod]? - if Int(_1!) & Int(1 << 6) != 0 {if let _ = reader.readInt32() { - _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PaymentFormMethod.self) - } } - var _13: Api.PaymentRequestedInfo? - if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { - _13 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo - } } - var _14: [Api.PaymentSavedCredentials]? - if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { - _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PaymentSavedCredentials.self) - } } - var _15: [Api.User]? - if let _ = reader.readInt32() { - _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) - } - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - let _c4 = _4 != nil - let _c5 = _5 != nil - let _c6 = (Int(_1!) & Int(1 << 5) == 0) || _6 != nil - let _c7 = _7 != nil - let _c8 = _8 != nil - let _c9 = _9 != nil - let _c10 = (Int(_1!) & Int(1 << 4) == 0) || _10 != nil - let _c11 = (Int(_1!) & Int(1 << 4) == 0) || _11 != nil - let _c12 = (Int(_1!) & Int(1 << 6) == 0) || _12 != nil - let _c13 = (Int(_1!) & Int(1 << 0) == 0) || _13 != nil - let _c14 = (Int(_1!) & Int(1 << 1) == 0) || _14 != nil - let _c15 = _15 != nil - if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { - return Api.payments.PaymentForm.paymentForm(flags: _1!, formId: _2!, botId: _3!, title: _4!, description: _5!, photo: _6, invoice: _7!, providerId: _8!, url: _9!, nativeProvider: _10, nativeParams: _11, additionalMethods: _12, savedInfo: _13, savedCredentials: _14, users: _15!) - } - else { - return nil - } - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api30.swift b/submodules/TelegramApi/Sources/Api30.swift index 3e5ca3e260..54afb14e4b 100644 --- a/submodules/TelegramApi/Sources/Api30.swift +++ b/submodules/TelegramApi/Sources/Api30.swift @@ -1,3 +1,121 @@ +public extension Api.payments { + enum PaymentForm: TypeConstructorDescription { + case paymentForm(flags: Int32, formId: Int64, botId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, providerId: Int64, url: String, nativeProvider: String?, nativeParams: Api.DataJSON?, additionalMethods: [Api.PaymentFormMethod]?, savedInfo: Api.PaymentRequestedInfo?, savedCredentials: [Api.PaymentSavedCredentials]?, users: [Api.User]) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users): + if boxed { + buffer.appendInt32(-1610250415) + } + serializeInt32(flags, buffer: buffer, boxed: false) + serializeInt64(formId, buffer: buffer, boxed: false) + serializeInt64(botId, buffer: buffer, boxed: false) + serializeString(title, buffer: buffer, boxed: false) + serializeString(description, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 5) != 0 {photo!.serialize(buffer, true)} + invoice.serialize(buffer, true) + serializeInt64(providerId, buffer: buffer, boxed: false) + serializeString(url, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 4) != 0 {serializeString(nativeProvider!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 4) != 0 {nativeParams!.serialize(buffer, true)} + if Int(flags) & Int(1 << 6) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(additionalMethods!.count)) + for item in additionalMethods! { + item.serialize(buffer, true) + }} + if Int(flags) & Int(1 << 0) != 0 {savedInfo!.serialize(buffer, true)} + if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261) + buffer.appendInt32(Int32(savedCredentials!.count)) + for item in savedCredentials! { + item.serialize(buffer, true) + }} + buffer.appendInt32(481674261) + buffer.appendInt32(Int32(users.count)) + for item in users { + item.serialize(buffer, true) + } + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .paymentForm(let flags, let formId, let botId, let title, let description, let photo, let invoice, let providerId, let url, let nativeProvider, let nativeParams, let additionalMethods, let savedInfo, let savedCredentials, let users): + return ("paymentForm", [("flags", flags as Any), ("formId", formId as Any), ("botId", botId as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("providerId", providerId as Any), ("url", url as Any), ("nativeProvider", nativeProvider as Any), ("nativeParams", nativeParams as Any), ("additionalMethods", additionalMethods as Any), ("savedInfo", savedInfo as Any), ("savedCredentials", savedCredentials as Any), ("users", users as Any)]) + } + } + + public static func parse_paymentForm(_ reader: BufferReader) -> PaymentForm? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Int64? + _2 = reader.readInt64() + var _3: Int64? + _3 = reader.readInt64() + var _4: String? + _4 = parseString(reader) + var _5: String? + _5 = parseString(reader) + var _6: Api.WebDocument? + if Int(_1!) & Int(1 << 5) != 0 {if let signature = reader.readInt32() { + _6 = Api.parse(reader, signature: signature) as? Api.WebDocument + } } + var _7: Api.Invoice? + if let signature = reader.readInt32() { + _7 = Api.parse(reader, signature: signature) as? Api.Invoice + } + var _8: Int64? + _8 = reader.readInt64() + var _9: String? + _9 = parseString(reader) + var _10: String? + if Int(_1!) & Int(1 << 4) != 0 {_10 = parseString(reader) } + var _11: Api.DataJSON? + if Int(_1!) & Int(1 << 4) != 0 {if let signature = reader.readInt32() { + _11 = Api.parse(reader, signature: signature) as? Api.DataJSON + } } + var _12: [Api.PaymentFormMethod]? + if Int(_1!) & Int(1 << 6) != 0 {if let _ = reader.readInt32() { + _12 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PaymentFormMethod.self) + } } + var _13: Api.PaymentRequestedInfo? + if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() { + _13 = Api.parse(reader, signature: signature) as? Api.PaymentRequestedInfo + } } + var _14: [Api.PaymentSavedCredentials]? + if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() { + _14 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PaymentSavedCredentials.self) + } } + var _15: [Api.User]? + if let _ = reader.readInt32() { + _15 = Api.parseVector(reader, elementSignature: 0, elementType: Api.User.self) + } + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + let _c4 = _4 != nil + let _c5 = _5 != nil + let _c6 = (Int(_1!) & Int(1 << 5) == 0) || _6 != nil + let _c7 = _7 != nil + let _c8 = _8 != nil + let _c9 = _9 != nil + let _c10 = (Int(_1!) & Int(1 << 4) == 0) || _10 != nil + let _c11 = (Int(_1!) & Int(1 << 4) == 0) || _11 != nil + let _c12 = (Int(_1!) & Int(1 << 6) == 0) || _12 != nil + let _c13 = (Int(_1!) & Int(1 << 0) == 0) || _13 != nil + let _c14 = (Int(_1!) & Int(1 << 1) == 0) || _14 != nil + let _c15 = _15 != nil + if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 { + return Api.payments.PaymentForm.paymentForm(flags: _1!, formId: _2!, botId: _3!, title: _4!, description: _5!, photo: _6, invoice: _7!, providerId: _8!, url: _9!, nativeProvider: _10, nativeParams: _11, additionalMethods: _12, savedInfo: _13, savedCredentials: _14, users: _15!) + } + else { + return nil + } + } + + } +} public extension Api.payments { enum PaymentReceipt: TypeConstructorDescription { case paymentReceipt(flags: Int32, date: Int32, botId: Int64, providerId: Int64, title: String, description: String, photo: Api.WebDocument?, invoice: Api.Invoice, info: Api.PaymentRequestedInfo?, shipping: Api.ShippingOption?, tipAmount: Int64?, currency: String, totalAmount: Int64, credentialsTitle: String, users: [Api.User]) diff --git a/submodules/TelegramApi/Sources/Api32.swift b/submodules/TelegramApi/Sources/Api32.swift index 5b224f22fc..fda6b6fbd3 100644 --- a/submodules/TelegramApi/Sources/Api32.swift +++ b/submodules/TelegramApi/Sources/Api32.swift @@ -3934,6 +3934,21 @@ public extension Api.functions.folders { }) } } +public extension Api.functions.fragment { + static func getCollectibleInfo(collectible: Api.InputCollectible) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-1105295942) + collectible.serialize(buffer, true) + return (FunctionDescription(name: "fragment.getCollectibleInfo", parameters: [("collectible", String(describing: collectible))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.fragment.CollectibleInfo? in + let reader = BufferReader(buffer) + var result: Api.fragment.CollectibleInfo? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.fragment.CollectibleInfo + } + return result + }) + } +} public extension Api.functions.help { static func acceptTermsOfService(id: Api.DataJSON) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -5851,6 +5866,22 @@ public extension Api.functions.messages { }) } } +public extension Api.functions.messages { + static func getMyStickers(offsetId: Int64, limit: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(-793386500) + serializeInt64(offsetId, buffer: buffer, boxed: false) + serializeInt32(limit, buffer: buffer, boxed: false) + return (FunctionDescription(name: "messages.getMyStickers", parameters: [("offsetId", String(describing: offsetId)), ("limit", String(describing: limit))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.messages.MyStickers? in + let reader = BufferReader(buffer) + var result: Api.messages.MyStickers? + if let signature = reader.readInt32() { + result = Api.parse(reader, signature: signature) as? Api.messages.MyStickers + } + return result + }) + } +} public extension Api.functions.messages { static func getOldFeaturedStickers(offset: Int32, limit: Int32, hash: Int64) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() @@ -7385,12 +7416,22 @@ public extension Api.functions.messages { } } public extension Api.functions.messages { - static func sendQuickReplyMessages(peer: Api.InputPeer, shortcutId: Int32) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + static func sendQuickReplyMessages(peer: Api.InputPeer, shortcutId: Int32, id: [Int32], randomId: [Int64]) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() - buffer.appendInt32(857029332) + buffer.appendInt32(1819610593) peer.serialize(buffer, true) serializeInt32(shortcutId, buffer: buffer, boxed: false) - return (FunctionDescription(name: "messages.sendQuickReplyMessages", parameters: [("peer", String(describing: peer)), ("shortcutId", String(describing: shortcutId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in + 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) + } + return (FunctionDescription(name: "messages.sendQuickReplyMessages", parameters: [("peer", String(describing: peer)), ("shortcutId", String(describing: shortcutId)), ("id", String(describing: id)), ("randomId", String(describing: randomId))]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Updates? in let reader = BufferReader(buffer) var result: Api.Updates? if let signature = reader.readInt32() { @@ -9444,6 +9485,22 @@ public extension Api.functions.stickers { }) } } +public extension Api.functions.stickers { + static func replaceSticker(sticker: Api.InputDocument, newSticker: Api.InputStickerSetItem) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { + let buffer = Buffer() + buffer.appendInt32(1184253338) + sticker.serialize(buffer, true) + newSticker.serialize(buffer, true) + return (FunctionDescription(name: "stickers.replaceSticker", parameters: [("sticker", String(describing: sticker)), ("newSticker", String(describing: newSticker))]), 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(flags: Int32, stickerset: Api.InputStickerSet, thumb: Api.InputDocument?, thumbDocumentId: Int64?) -> (FunctionDescription, Buffer, DeserializeFunctionResponse) { let buffer = Buffer() diff --git a/submodules/TelegramApi/Sources/Api7.swift b/submodules/TelegramApi/Sources/Api7.swift index cbdf0ebf38..7ad68b056b 100644 --- a/submodules/TelegramApi/Sources/Api7.swift +++ b/submodules/TelegramApi/Sources/Api7.swift @@ -712,6 +712,62 @@ public extension Api { } } +public extension Api { + enum InputCollectible: TypeConstructorDescription { + case inputCollectiblePhone(phone: String) + case inputCollectibleUsername(username: String) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputCollectiblePhone(let phone): + if boxed { + buffer.appendInt32(-1562241884) + } + serializeString(phone, buffer: buffer, boxed: false) + break + case .inputCollectibleUsername(let username): + if boxed { + buffer.appendInt32(-476815191) + } + serializeString(username, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputCollectiblePhone(let phone): + return ("inputCollectiblePhone", [("phone", phone as Any)]) + case .inputCollectibleUsername(let username): + return ("inputCollectibleUsername", [("username", username as Any)]) + } + } + + public static func parse_inputCollectiblePhone(_ reader: BufferReader) -> InputCollectible? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.InputCollectible.inputCollectiblePhone(phone: _1!) + } + else { + return nil + } + } + public static func parse_inputCollectibleUsername(_ reader: BufferReader) -> InputCollectible? { + var _1: String? + _1 = parseString(reader) + let _c1 = _1 != nil + if _c1 { + return Api.InputCollectible.inputCollectibleUsername(username: _1!) + } + else { + return nil + } + } + + } +} public extension Api { enum InputContact: TypeConstructorDescription { case inputPhoneContact(clientId: Int64, phone: String, firstName: String, lastName: String) @@ -1102,313 +1158,3 @@ public extension Api { } } -public extension Api { - indirect enum InputFileLocation: TypeConstructorDescription { - case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String) - case inputEncryptedFileLocation(id: Int64, accessHash: Int64) - case inputFileLocation(volumeId: Int64, localId: Int32, secret: Int64, fileReference: Buffer) - case inputGroupCallStream(flags: Int32, call: Api.InputGroupCall, timeMs: Int64, scale: Int32, videoChannel: Int32?, videoQuality: Int32?) - case inputPeerPhotoFileLocation(flags: Int32, peer: Api.InputPeer, photoId: Int64) - case inputPhotoFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String) - case inputPhotoLegacyFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, volumeId: Int64, localId: Int32, secret: Int64) - case inputSecureFileLocation(id: Int64, accessHash: Int64) - case inputStickerSetThumb(stickerset: Api.InputStickerSet, thumbVersion: Int32) - case inputTakeoutFileLocation - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize): - if boxed { - buffer.appendInt32(-1160743548) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeBytes(fileReference, buffer: buffer, boxed: false) - serializeString(thumbSize, buffer: buffer, boxed: false) - break - case .inputEncryptedFileLocation(let id, let accessHash): - if boxed { - buffer.appendInt32(-182231723) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - break - case .inputFileLocation(let volumeId, let localId, let secret, let fileReference): - if boxed { - buffer.appendInt32(-539317279) - } - serializeInt64(volumeId, buffer: buffer, boxed: false) - serializeInt32(localId, buffer: buffer, boxed: false) - serializeInt64(secret, buffer: buffer, boxed: false) - serializeBytes(fileReference, buffer: buffer, boxed: false) - break - case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality): - if boxed { - buffer.appendInt32(93890858) - } - serializeInt32(flags, buffer: buffer, boxed: false) - call.serialize(buffer, true) - serializeInt64(timeMs, buffer: buffer, boxed: false) - serializeInt32(scale, buffer: buffer, boxed: false) - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoChannel!, buffer: buffer, boxed: false)} - if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoQuality!, buffer: buffer, boxed: false)} - break - case .inputPeerPhotoFileLocation(let flags, let peer, let photoId): - if boxed { - buffer.appendInt32(925204121) - } - serializeInt32(flags, buffer: buffer, boxed: false) - peer.serialize(buffer, true) - serializeInt64(photoId, buffer: buffer, boxed: false) - break - case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize): - if boxed { - buffer.appendInt32(1075322878) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeBytes(fileReference, buffer: buffer, boxed: false) - serializeString(thumbSize, buffer: buffer, boxed: false) - break - case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret): - if boxed { - buffer.appendInt32(-667654413) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - serializeBytes(fileReference, buffer: buffer, boxed: false) - serializeInt64(volumeId, buffer: buffer, boxed: false) - serializeInt32(localId, buffer: buffer, boxed: false) - serializeInt64(secret, buffer: buffer, boxed: false) - break - case .inputSecureFileLocation(let id, let accessHash): - if boxed { - buffer.appendInt32(-876089816) - } - serializeInt64(id, buffer: buffer, boxed: false) - serializeInt64(accessHash, buffer: buffer, boxed: false) - break - case .inputStickerSetThumb(let stickerset, let thumbVersion): - if boxed { - buffer.appendInt32(-1652231205) - } - stickerset.serialize(buffer, true) - serializeInt32(thumbVersion, buffer: buffer, boxed: false) - break - case .inputTakeoutFileLocation: - if boxed { - buffer.appendInt32(700340377) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize): - return ("inputDocumentFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)]) - case .inputEncryptedFileLocation(let id, let accessHash): - return ("inputEncryptedFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)]) - case .inputFileLocation(let volumeId, let localId, let secret, let fileReference): - return ("inputFileLocation", [("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any), ("fileReference", fileReference as Any)]) - case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality): - return ("inputGroupCallStream", [("flags", flags as Any), ("call", call as Any), ("timeMs", timeMs as Any), ("scale", scale as Any), ("videoChannel", videoChannel as Any), ("videoQuality", videoQuality as Any)]) - case .inputPeerPhotoFileLocation(let flags, let peer, let photoId): - return ("inputPeerPhotoFileLocation", [("flags", flags as Any), ("peer", peer as Any), ("photoId", photoId as Any)]) - case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize): - return ("inputPhotoFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)]) - case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret): - return ("inputPhotoLegacyFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any)]) - case .inputSecureFileLocation(let id, let accessHash): - return ("inputSecureFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)]) - case .inputStickerSetThumb(let stickerset, let thumbVersion): - return ("inputStickerSetThumb", [("stickerset", stickerset as Any), ("thumbVersion", thumbVersion as Any)]) - case .inputTakeoutFileLocation: - return ("inputTakeoutFileLocation", []) - } - } - - public static func parse_inputDocumentFileLocation(_ reader: BufferReader) -> InputFileLocation? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: Buffer? - _3 = parseBytes(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.InputFileLocation.inputDocumentFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!) - } - else { - return nil - } - } - public static func parse_inputEncryptedFileLocation(_ reader: BufferReader) -> InputFileLocation? { - 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.InputFileLocation.inputEncryptedFileLocation(id: _1!, accessHash: _2!) - } - else { - return nil - } - } - public static func parse_inputFileLocation(_ reader: BufferReader) -> InputFileLocation? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int32? - _2 = reader.readInt32() - var _3: Int64? - _3 = reader.readInt64() - 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.InputFileLocation.inputFileLocation(volumeId: _1!, localId: _2!, secret: _3!, fileReference: _4!) - } - else { - return nil - } - } - public static func parse_inputGroupCallStream(_ reader: BufferReader) -> InputFileLocation? { - 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: Int64? - _3 = reader.readInt64() - var _4: Int32? - _4 = reader.readInt32() - var _5: Int32? - if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() } - 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.InputFileLocation.inputGroupCallStream(flags: _1!, call: _2!, timeMs: _3!, scale: _4!, videoChannel: _5, videoQuality: _6) - } - else { - return nil - } - } - public static func parse_inputPeerPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? { - var _1: Int32? - _1 = reader.readInt32() - var _2: Api.InputPeer? - if let signature = reader.readInt32() { - _2 = Api.parse(reader, signature: signature) as? Api.InputPeer - } - var _3: Int64? - _3 = reader.readInt64() - let _c1 = _1 != nil - let _c2 = _2 != nil - let _c3 = _3 != nil - if _c1 && _c2 && _c3 { - return Api.InputFileLocation.inputPeerPhotoFileLocation(flags: _1!, peer: _2!, photoId: _3!) - } - else { - return nil - } - } - public static func parse_inputPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: Buffer? - _3 = parseBytes(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.InputFileLocation.inputPhotoFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!) - } - else { - return nil - } - } - public static func parse_inputPhotoLegacyFileLocation(_ reader: BufferReader) -> InputFileLocation? { - var _1: Int64? - _1 = reader.readInt64() - var _2: Int64? - _2 = reader.readInt64() - var _3: Buffer? - _3 = parseBytes(reader) - var _4: Int64? - _4 = reader.readInt64() - var _5: Int32? - _5 = reader.readInt32() - var _6: Int64? - _6 = reader.readInt64() - 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.InputFileLocation.inputPhotoLegacyFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, volumeId: _4!, localId: _5!, secret: _6!) - } - else { - return nil - } - } - public static func parse_inputSecureFileLocation(_ reader: BufferReader) -> InputFileLocation? { - 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.InputFileLocation.inputSecureFileLocation(id: _1!, accessHash: _2!) - } - else { - return nil - } - } - public static func parse_inputStickerSetThumb(_ reader: BufferReader) -> InputFileLocation? { - var _1: Api.InputStickerSet? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputStickerSet - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.InputFileLocation.inputStickerSetThumb(stickerset: _1!, thumbVersion: _2!) - } - else { - return nil - } - } - public static func parse_inputTakeoutFileLocation(_ reader: BufferReader) -> InputFileLocation? { - return Api.InputFileLocation.inputTakeoutFileLocation - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api8.swift b/submodules/TelegramApi/Sources/Api8.swift index 8048250b31..3276fce952 100644 --- a/submodules/TelegramApi/Sources/Api8.swift +++ b/submodules/TelegramApi/Sources/Api8.swift @@ -1,3 +1,313 @@ +public extension Api { + indirect enum InputFileLocation: TypeConstructorDescription { + case inputDocumentFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String) + case inputEncryptedFileLocation(id: Int64, accessHash: Int64) + case inputFileLocation(volumeId: Int64, localId: Int32, secret: Int64, fileReference: Buffer) + case inputGroupCallStream(flags: Int32, call: Api.InputGroupCall, timeMs: Int64, scale: Int32, videoChannel: Int32?, videoQuality: Int32?) + case inputPeerPhotoFileLocation(flags: Int32, peer: Api.InputPeer, photoId: Int64) + case inputPhotoFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, thumbSize: String) + case inputPhotoLegacyFileLocation(id: Int64, accessHash: Int64, fileReference: Buffer, volumeId: Int64, localId: Int32, secret: Int64) + case inputSecureFileLocation(id: Int64, accessHash: Int64) + case inputStickerSetThumb(stickerset: Api.InputStickerSet, thumbVersion: Int32) + case inputTakeoutFileLocation + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize): + if boxed { + buffer.appendInt32(-1160743548) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeBytes(fileReference, buffer: buffer, boxed: false) + serializeString(thumbSize, buffer: buffer, boxed: false) + break + case .inputEncryptedFileLocation(let id, let accessHash): + if boxed { + buffer.appendInt32(-182231723) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + break + case .inputFileLocation(let volumeId, let localId, let secret, let fileReference): + if boxed { + buffer.appendInt32(-539317279) + } + serializeInt64(volumeId, buffer: buffer, boxed: false) + serializeInt32(localId, buffer: buffer, boxed: false) + serializeInt64(secret, buffer: buffer, boxed: false) + serializeBytes(fileReference, buffer: buffer, boxed: false) + break + case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality): + if boxed { + buffer.appendInt32(93890858) + } + serializeInt32(flags, buffer: buffer, boxed: false) + call.serialize(buffer, true) + serializeInt64(timeMs, buffer: buffer, boxed: false) + serializeInt32(scale, buffer: buffer, boxed: false) + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoChannel!, buffer: buffer, boxed: false)} + if Int(flags) & Int(1 << 0) != 0 {serializeInt32(videoQuality!, buffer: buffer, boxed: false)} + break + case .inputPeerPhotoFileLocation(let flags, let peer, let photoId): + if boxed { + buffer.appendInt32(925204121) + } + serializeInt32(flags, buffer: buffer, boxed: false) + peer.serialize(buffer, true) + serializeInt64(photoId, buffer: buffer, boxed: false) + break + case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize): + if boxed { + buffer.appendInt32(1075322878) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeBytes(fileReference, buffer: buffer, boxed: false) + serializeString(thumbSize, buffer: buffer, boxed: false) + break + case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret): + if boxed { + buffer.appendInt32(-667654413) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + serializeBytes(fileReference, buffer: buffer, boxed: false) + serializeInt64(volumeId, buffer: buffer, boxed: false) + serializeInt32(localId, buffer: buffer, boxed: false) + serializeInt64(secret, buffer: buffer, boxed: false) + break + case .inputSecureFileLocation(let id, let accessHash): + if boxed { + buffer.appendInt32(-876089816) + } + serializeInt64(id, buffer: buffer, boxed: false) + serializeInt64(accessHash, buffer: buffer, boxed: false) + break + case .inputStickerSetThumb(let stickerset, let thumbVersion): + if boxed { + buffer.appendInt32(-1652231205) + } + stickerset.serialize(buffer, true) + serializeInt32(thumbVersion, buffer: buffer, boxed: false) + break + case .inputTakeoutFileLocation: + if boxed { + buffer.appendInt32(700340377) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputDocumentFileLocation(let id, let accessHash, let fileReference, let thumbSize): + return ("inputDocumentFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)]) + case .inputEncryptedFileLocation(let id, let accessHash): + return ("inputEncryptedFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)]) + case .inputFileLocation(let volumeId, let localId, let secret, let fileReference): + return ("inputFileLocation", [("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any), ("fileReference", fileReference as Any)]) + case .inputGroupCallStream(let flags, let call, let timeMs, let scale, let videoChannel, let videoQuality): + return ("inputGroupCallStream", [("flags", flags as Any), ("call", call as Any), ("timeMs", timeMs as Any), ("scale", scale as Any), ("videoChannel", videoChannel as Any), ("videoQuality", videoQuality as Any)]) + case .inputPeerPhotoFileLocation(let flags, let peer, let photoId): + return ("inputPeerPhotoFileLocation", [("flags", flags as Any), ("peer", peer as Any), ("photoId", photoId as Any)]) + case .inputPhotoFileLocation(let id, let accessHash, let fileReference, let thumbSize): + return ("inputPhotoFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("thumbSize", thumbSize as Any)]) + case .inputPhotoLegacyFileLocation(let id, let accessHash, let fileReference, let volumeId, let localId, let secret): + return ("inputPhotoLegacyFileLocation", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any), ("volumeId", volumeId as Any), ("localId", localId as Any), ("secret", secret as Any)]) + case .inputSecureFileLocation(let id, let accessHash): + return ("inputSecureFileLocation", [("id", id as Any), ("accessHash", accessHash as Any)]) + case .inputStickerSetThumb(let stickerset, let thumbVersion): + return ("inputStickerSetThumb", [("stickerset", stickerset as Any), ("thumbVersion", thumbVersion as Any)]) + case .inputTakeoutFileLocation: + return ("inputTakeoutFileLocation", []) + } + } + + public static func parse_inputDocumentFileLocation(_ reader: BufferReader) -> InputFileLocation? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Buffer? + _3 = parseBytes(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.InputFileLocation.inputDocumentFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!) + } + else { + return nil + } + } + public static func parse_inputEncryptedFileLocation(_ reader: BufferReader) -> InputFileLocation? { + 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.InputFileLocation.inputEncryptedFileLocation(id: _1!, accessHash: _2!) + } + else { + return nil + } + } + public static func parse_inputFileLocation(_ reader: BufferReader) -> InputFileLocation? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int32? + _2 = reader.readInt32() + var _3: Int64? + _3 = reader.readInt64() + 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.InputFileLocation.inputFileLocation(volumeId: _1!, localId: _2!, secret: _3!, fileReference: _4!) + } + else { + return nil + } + } + public static func parse_inputGroupCallStream(_ reader: BufferReader) -> InputFileLocation? { + 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: Int64? + _3 = reader.readInt64() + var _4: Int32? + _4 = reader.readInt32() + var _5: Int32? + if Int(_1!) & Int(1 << 0) != 0 {_5 = reader.readInt32() } + 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.InputFileLocation.inputGroupCallStream(flags: _1!, call: _2!, timeMs: _3!, scale: _4!, videoChannel: _5, videoQuality: _6) + } + else { + return nil + } + } + public static func parse_inputPeerPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? { + var _1: Int32? + _1 = reader.readInt32() + var _2: Api.InputPeer? + if let signature = reader.readInt32() { + _2 = Api.parse(reader, signature: signature) as? Api.InputPeer + } + var _3: Int64? + _3 = reader.readInt64() + let _c1 = _1 != nil + let _c2 = _2 != nil + let _c3 = _3 != nil + if _c1 && _c2 && _c3 { + return Api.InputFileLocation.inputPeerPhotoFileLocation(flags: _1!, peer: _2!, photoId: _3!) + } + else { + return nil + } + } + public static func parse_inputPhotoFileLocation(_ reader: BufferReader) -> InputFileLocation? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Buffer? + _3 = parseBytes(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.InputFileLocation.inputPhotoFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, thumbSize: _4!) + } + else { + return nil + } + } + public static func parse_inputPhotoLegacyFileLocation(_ reader: BufferReader) -> InputFileLocation? { + var _1: Int64? + _1 = reader.readInt64() + var _2: Int64? + _2 = reader.readInt64() + var _3: Buffer? + _3 = parseBytes(reader) + var _4: Int64? + _4 = reader.readInt64() + var _5: Int32? + _5 = reader.readInt32() + var _6: Int64? + _6 = reader.readInt64() + 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.InputFileLocation.inputPhotoLegacyFileLocation(id: _1!, accessHash: _2!, fileReference: _3!, volumeId: _4!, localId: _5!, secret: _6!) + } + else { + return nil + } + } + public static func parse_inputSecureFileLocation(_ reader: BufferReader) -> InputFileLocation? { + 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.InputFileLocation.inputSecureFileLocation(id: _1!, accessHash: _2!) + } + else { + return nil + } + } + public static func parse_inputStickerSetThumb(_ reader: BufferReader) -> InputFileLocation? { + var _1: Api.InputStickerSet? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputStickerSet + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.InputFileLocation.inputStickerSetThumb(stickerset: _1!, thumbVersion: _2!) + } + else { + return nil + } + } + public static func parse_inputTakeoutFileLocation(_ reader: BufferReader) -> InputFileLocation? { + return Api.InputFileLocation.inputTakeoutFileLocation + } + + } +} public extension Api { indirect enum InputFolderPeer: TypeConstructorDescription { case inputFolderPeer(peer: Api.InputPeer, folderId: Int32) @@ -884,195 +1194,3 @@ public extension Api { } } -public extension Api { - enum InputMessage: TypeConstructorDescription { - case inputMessageCallbackQuery(id: Int32, queryId: Int64) - case inputMessageID(id: Int32) - case inputMessagePinned - case inputMessageReplyTo(id: Int32) - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputMessageCallbackQuery(let id, let queryId): - if boxed { - buffer.appendInt32(-1392895362) - } - serializeInt32(id, buffer: buffer, boxed: false) - serializeInt64(queryId, buffer: buffer, boxed: false) - break - case .inputMessageID(let id): - if boxed { - buffer.appendInt32(-1502174430) - } - serializeInt32(id, buffer: buffer, boxed: false) - break - case .inputMessagePinned: - if boxed { - buffer.appendInt32(-2037963464) - } - - break - case .inputMessageReplyTo(let id): - if boxed { - buffer.appendInt32(-1160215659) - } - serializeInt32(id, buffer: buffer, boxed: false) - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputMessageCallbackQuery(let id, let queryId): - return ("inputMessageCallbackQuery", [("id", id as Any), ("queryId", queryId as Any)]) - case .inputMessageID(let id): - return ("inputMessageID", [("id", id as Any)]) - case .inputMessagePinned: - return ("inputMessagePinned", []) - case .inputMessageReplyTo(let id): - return ("inputMessageReplyTo", [("id", id as Any)]) - } - } - - public static func parse_inputMessageCallbackQuery(_ reader: BufferReader) -> InputMessage? { - 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.InputMessage.inputMessageCallbackQuery(id: _1!, queryId: _2!) - } - else { - return nil - } - } - public static func parse_inputMessageID(_ reader: BufferReader) -> InputMessage? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.InputMessage.inputMessageID(id: _1!) - } - else { - return nil - } - } - public static func parse_inputMessagePinned(_ reader: BufferReader) -> InputMessage? { - return Api.InputMessage.inputMessagePinned - } - public static func parse_inputMessageReplyTo(_ reader: BufferReader) -> InputMessage? { - var _1: Int32? - _1 = reader.readInt32() - let _c1 = _1 != nil - if _c1 { - return Api.InputMessage.inputMessageReplyTo(id: _1!) - } - else { - return nil - } - } - - } -} -public extension Api { - indirect enum InputNotifyPeer: TypeConstructorDescription { - case inputNotifyBroadcasts - case inputNotifyChats - case inputNotifyForumTopic(peer: Api.InputPeer, topMsgId: Int32) - case inputNotifyPeer(peer: Api.InputPeer) - case inputNotifyUsers - - public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { - switch self { - case .inputNotifyBroadcasts: - if boxed { - buffer.appendInt32(-1311015810) - } - - break - case .inputNotifyChats: - if boxed { - buffer.appendInt32(1251338318) - } - - break - case .inputNotifyForumTopic(let peer, let topMsgId): - if boxed { - buffer.appendInt32(1548122514) - } - peer.serialize(buffer, true) - serializeInt32(topMsgId, buffer: buffer, boxed: false) - break - case .inputNotifyPeer(let peer): - if boxed { - buffer.appendInt32(-1195615476) - } - peer.serialize(buffer, true) - break - case .inputNotifyUsers: - if boxed { - buffer.appendInt32(423314455) - } - - break - } - } - - public func descriptionFields() -> (String, [(String, Any)]) { - switch self { - case .inputNotifyBroadcasts: - return ("inputNotifyBroadcasts", []) - case .inputNotifyChats: - return ("inputNotifyChats", []) - case .inputNotifyForumTopic(let peer, let topMsgId): - return ("inputNotifyForumTopic", [("peer", peer as Any), ("topMsgId", topMsgId as Any)]) - case .inputNotifyPeer(let peer): - return ("inputNotifyPeer", [("peer", peer as Any)]) - case .inputNotifyUsers: - return ("inputNotifyUsers", []) - } - } - - public static func parse_inputNotifyBroadcasts(_ reader: BufferReader) -> InputNotifyPeer? { - return Api.InputNotifyPeer.inputNotifyBroadcasts - } - public static func parse_inputNotifyChats(_ reader: BufferReader) -> InputNotifyPeer? { - return Api.InputNotifyPeer.inputNotifyChats - } - public static func parse_inputNotifyForumTopic(_ reader: BufferReader) -> InputNotifyPeer? { - var _1: Api.InputPeer? - if let signature = reader.readInt32() { - _1 = Api.parse(reader, signature: signature) as? Api.InputPeer - } - var _2: Int32? - _2 = reader.readInt32() - let _c1 = _1 != nil - let _c2 = _2 != nil - if _c1 && _c2 { - return Api.InputNotifyPeer.inputNotifyForumTopic(peer: _1!, topMsgId: _2!) - } - else { - return nil - } - } - public static func parse_inputNotifyPeer(_ reader: BufferReader) -> InputNotifyPeer? { - 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.InputNotifyPeer.inputNotifyPeer(peer: _1!) - } - else { - return nil - } - } - public static func parse_inputNotifyUsers(_ reader: BufferReader) -> InputNotifyPeer? { - return Api.InputNotifyPeer.inputNotifyUsers - } - - } -} diff --git a/submodules/TelegramApi/Sources/Api9.swift b/submodules/TelegramApi/Sources/Api9.swift index 8605e3757f..b838506bde 100644 --- a/submodules/TelegramApi/Sources/Api9.swift +++ b/submodules/TelegramApi/Sources/Api9.swift @@ -1,3 +1,195 @@ +public extension Api { + enum InputMessage: TypeConstructorDescription { + case inputMessageCallbackQuery(id: Int32, queryId: Int64) + case inputMessageID(id: Int32) + case inputMessagePinned + case inputMessageReplyTo(id: Int32) + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputMessageCallbackQuery(let id, let queryId): + if boxed { + buffer.appendInt32(-1392895362) + } + serializeInt32(id, buffer: buffer, boxed: false) + serializeInt64(queryId, buffer: buffer, boxed: false) + break + case .inputMessageID(let id): + if boxed { + buffer.appendInt32(-1502174430) + } + serializeInt32(id, buffer: buffer, boxed: false) + break + case .inputMessagePinned: + if boxed { + buffer.appendInt32(-2037963464) + } + + break + case .inputMessageReplyTo(let id): + if boxed { + buffer.appendInt32(-1160215659) + } + serializeInt32(id, buffer: buffer, boxed: false) + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputMessageCallbackQuery(let id, let queryId): + return ("inputMessageCallbackQuery", [("id", id as Any), ("queryId", queryId as Any)]) + case .inputMessageID(let id): + return ("inputMessageID", [("id", id as Any)]) + case .inputMessagePinned: + return ("inputMessagePinned", []) + case .inputMessageReplyTo(let id): + return ("inputMessageReplyTo", [("id", id as Any)]) + } + } + + public static func parse_inputMessageCallbackQuery(_ reader: BufferReader) -> InputMessage? { + 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.InputMessage.inputMessageCallbackQuery(id: _1!, queryId: _2!) + } + else { + return nil + } + } + public static func parse_inputMessageID(_ reader: BufferReader) -> InputMessage? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.InputMessage.inputMessageID(id: _1!) + } + else { + return nil + } + } + public static func parse_inputMessagePinned(_ reader: BufferReader) -> InputMessage? { + return Api.InputMessage.inputMessagePinned + } + public static func parse_inputMessageReplyTo(_ reader: BufferReader) -> InputMessage? { + var _1: Int32? + _1 = reader.readInt32() + let _c1 = _1 != nil + if _c1 { + return Api.InputMessage.inputMessageReplyTo(id: _1!) + } + else { + return nil + } + } + + } +} +public extension Api { + indirect enum InputNotifyPeer: TypeConstructorDescription { + case inputNotifyBroadcasts + case inputNotifyChats + case inputNotifyForumTopic(peer: Api.InputPeer, topMsgId: Int32) + case inputNotifyPeer(peer: Api.InputPeer) + case inputNotifyUsers + + public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) { + switch self { + case .inputNotifyBroadcasts: + if boxed { + buffer.appendInt32(-1311015810) + } + + break + case .inputNotifyChats: + if boxed { + buffer.appendInt32(1251338318) + } + + break + case .inputNotifyForumTopic(let peer, let topMsgId): + if boxed { + buffer.appendInt32(1548122514) + } + peer.serialize(buffer, true) + serializeInt32(topMsgId, buffer: buffer, boxed: false) + break + case .inputNotifyPeer(let peer): + if boxed { + buffer.appendInt32(-1195615476) + } + peer.serialize(buffer, true) + break + case .inputNotifyUsers: + if boxed { + buffer.appendInt32(423314455) + } + + break + } + } + + public func descriptionFields() -> (String, [(String, Any)]) { + switch self { + case .inputNotifyBroadcasts: + return ("inputNotifyBroadcasts", []) + case .inputNotifyChats: + return ("inputNotifyChats", []) + case .inputNotifyForumTopic(let peer, let topMsgId): + return ("inputNotifyForumTopic", [("peer", peer as Any), ("topMsgId", topMsgId as Any)]) + case .inputNotifyPeer(let peer): + return ("inputNotifyPeer", [("peer", peer as Any)]) + case .inputNotifyUsers: + return ("inputNotifyUsers", []) + } + } + + public static func parse_inputNotifyBroadcasts(_ reader: BufferReader) -> InputNotifyPeer? { + return Api.InputNotifyPeer.inputNotifyBroadcasts + } + public static func parse_inputNotifyChats(_ reader: BufferReader) -> InputNotifyPeer? { + return Api.InputNotifyPeer.inputNotifyChats + } + public static func parse_inputNotifyForumTopic(_ reader: BufferReader) -> InputNotifyPeer? { + var _1: Api.InputPeer? + if let signature = reader.readInt32() { + _1 = Api.parse(reader, signature: signature) as? Api.InputPeer + } + var _2: Int32? + _2 = reader.readInt32() + let _c1 = _1 != nil + let _c2 = _2 != nil + if _c1 && _c2 { + return Api.InputNotifyPeer.inputNotifyForumTopic(peer: _1!, topMsgId: _2!) + } + else { + return nil + } + } + public static func parse_inputNotifyPeer(_ reader: BufferReader) -> InputNotifyPeer? { + 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.InputNotifyPeer.inputNotifyPeer(peer: _1!) + } + else { + return nil + } + } + public static func parse_inputNotifyUsers(_ reader: BufferReader) -> InputNotifyPeer? { + return Api.InputNotifyPeer.inputNotifyUsers + } + + } +} public extension Api { enum InputPaymentCredentials: TypeConstructorDescription { case inputPaymentCredentials(flags: Int32, data: Api.DataJSON) @@ -584,183 +776,3 @@ public extension Api { } } -public extension Api { - enum InputPrivacyRule: TypeConstructorDescription { - case inputPrivacyValueAllowAll - case inputPrivacyValueAllowChatParticipants(chats: [Int64]) - case inputPrivacyValueAllowCloseFriends - 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 .inputPrivacyValueAllowCloseFriends: - if boxed { - buffer.appendInt32(793067081) - } - - 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", chats as Any)]) - case .inputPrivacyValueAllowCloseFriends: - return ("inputPrivacyValueAllowCloseFriends", []) - case .inputPrivacyValueAllowContacts: - return ("inputPrivacyValueAllowContacts", []) - case .inputPrivacyValueAllowUsers(let users): - return ("inputPrivacyValueAllowUsers", [("users", users as Any)]) - case .inputPrivacyValueDisallowAll: - return ("inputPrivacyValueDisallowAll", []) - case .inputPrivacyValueDisallowChatParticipants(let chats): - return ("inputPrivacyValueDisallowChatParticipants", [("chats", chats as Any)]) - case .inputPrivacyValueDisallowContacts: - return ("inputPrivacyValueDisallowContacts", []) - case .inputPrivacyValueDisallowUsers(let users): - return ("inputPrivacyValueDisallowUsers", [("users", users as Any)]) - } - } - - 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_inputPrivacyValueAllowCloseFriends(_ reader: BufferReader) -> InputPrivacyRule? { - return Api.InputPrivacyRule.inputPrivacyValueAllowCloseFriends - } - 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 - } - } - - } -} diff --git a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift index 55646590ff..186d35e138 100644 --- a/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift +++ b/submodules/TelegramCallsUI/Sources/VoiceChatJoinScreen.swift @@ -686,6 +686,9 @@ final class VoiceChatPreviewContentNode: ASDisplayNode, ShareContentContainerNod func setEnsurePeerVisibleOnLayout(_ peerId: PeerId?) { } + func setDidBeginDragging(_ f: (() -> Void)?) { + } + func setContentOffsetUpdated(_ f: ((CGFloat, ContainedViewLayoutTransition) -> Void)?) { self.contentOffsetUpdated = f } diff --git a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift index 5ecd19cfc1..86121ae367 100644 --- a/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift +++ b/submodules/TelegramCore/Sources/ApiUtils/StoreMessage_Telegram.swift @@ -126,7 +126,7 @@ public func tagsForStoreMessage(incoming: Bool, attributes: [MessageAttribute], func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? { switch messsage { - case let .message(_, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): let chatPeerId = messagePeerId return chatPeerId.peerId case let .messageEmpty(_, _, peerId): @@ -142,7 +142,7 @@ func apiMessagePeerId(_ messsage: Api.Message) -> PeerId? { func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] { switch message { - case let .message(_, _, fromId, _, chatPeerId, savedPeerId, fwdHeader, viaBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, _, fromId, _, chatPeerId, savedPeerId, fwdHeader, viaBotId, replyTo, _, _, media, _, entities, _, _, _, _, _, _, _, _, _, _): let peerId: PeerId = chatPeerId.peerId var result = [peerId] @@ -263,7 +263,7 @@ func apiMessagePeerIds(_ message: Api.Message) -> [PeerId] { func apiMessageAssociatedMessageIds(_ message: Api.Message) -> (replyIds: ReferencedReplyMessageIds, generalIds: [MessageId])? { switch message { - case let .message(_, id, _, _, chatPeerId, _, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, id, _, _, chatPeerId, _, _, _, replyTo, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): if let replyTo = replyTo { let peerId: PeerId = chatPeerId.peerId @@ -597,7 +597,7 @@ func messageTextEntitiesFromApiEntities(_ entities: [Api.MessageEntity]) -> [Mes extension StoreMessage { convenience init?(apiMessage: Api.Message, accountPeerId: PeerId, peerIsForum: Bool, namespace: MessageId.Namespace = Namespaces.Message.Cloud) { switch apiMessage { - case let .message(flags, id, fromId, boosts, chatPeerId, savedPeerId, fwdFrom, viaBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId): + case let .message(flags, _, id, fromId, boosts, chatPeerId, savedPeerId, fwdFrom, viaBotId, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId): let resolvedFromId = fromId?.peerId ?? chatPeerId.peerId var namespace = namespace diff --git a/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift b/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift index 0a2a0b1fb4..cfb0b59954 100644 --- a/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift +++ b/submodules/TelegramCore/Sources/State/ApplyUpdateMessage.swift @@ -96,7 +96,7 @@ func applyUpdateMessage(postbox: Postbox, stateManager: AccountStateManager, mes var updatedTimestamp: Int32? if let apiMessage = apiMessage { switch apiMessage { - case let .message(_, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _): updatedTimestamp = date case .messageEmpty: break diff --git a/submodules/TelegramCore/Sources/State/Serialization.swift b/submodules/TelegramCore/Sources/State/Serialization.swift index 6e1311188e..03166bd199 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 176 + return 177 } public func parseMessage(_ data: Data!) -> Any! { diff --git a/submodules/TelegramCore/Sources/State/UpdateMessageService.swift b/submodules/TelegramCore/Sources/State/UpdateMessageService.swift index 279064d68a..2976fef9ca 100644 --- a/submodules/TelegramCore/Sources/State/UpdateMessageService.swift +++ b/submodules/TelegramCore/Sources/State/UpdateMessageService.swift @@ -58,7 +58,7 @@ class UpdateMessageService: NSObject, MTMessageService { self.putNext(groups) } case let .updateShortChatMessage(flags, id, fromId, chatId, message, pts, ptsCount, date, fwdFrom, viaBotId, replyHeader, entities, ttlPeriod): - let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: .peerUser(userId: fromId), fromBoostsApplied: nil, peerId: Api.Peer.peerChat(chatId: chatId), savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil) + let generatedMessage = Api.Message.message(flags: flags, flags2: 0, id: id, fromId: .peerUser(userId: fromId), fromBoostsApplied: nil, peerId: Api.Peer.peerChat(chatId: chatId), savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil) let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount) let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil) if groups.count != 0 { @@ -74,7 +74,7 @@ class UpdateMessageService: NSObject, MTMessageService { let generatedPeerId = Api.Peer.peerUser(userId: userId) - let generatedMessage = Api.Message.message(flags: flags, id: id, fromId: generatedFromId, fromBoostsApplied: nil, peerId: generatedPeerId, savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil) + let generatedMessage = Api.Message.message(flags: flags, flags2: 0, id: id, fromId: generatedFromId, fromBoostsApplied: nil, peerId: generatedPeerId, savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil) let update = Api.Update.updateNewMessage(message: generatedMessage, pts: pts, ptsCount: ptsCount) let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil) if groups.count != 0 { diff --git a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift index a7fcc88093..a5f7b9db77 100644 --- a/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift +++ b/submodules/TelegramCore/Sources/State/UpdatesApiUtils.swift @@ -104,7 +104,7 @@ extension Api.MessageMedia { extension Api.Message { var rawId: Int32 { switch self { - case let .message(_, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, id, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): return id case let .messageEmpty(_, id, _): return id @@ -115,7 +115,7 @@ extension Api.Message { func id(namespace: MessageId.Namespace = Namespaces.Message.Cloud) -> MessageId? { switch self { - case let .message(_, id, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, id, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): let peerId: PeerId = messagePeerId.peerId return MessageId(peerId: peerId, namespace: namespace, id: id) case let .messageEmpty(_, id, peerId): @@ -132,7 +132,7 @@ extension Api.Message { var peerId: PeerId? { switch self { - case let .message(_, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, _, _, _, messagePeerId, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _): let peerId: PeerId = messagePeerId.peerId return peerId case let .messageEmpty(_, _, peerId): @@ -145,7 +145,7 @@ extension Api.Message { var timestamp: Int32? { switch self { - case let .message(_, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, _, _, _, _, _, _, _, _, date, _, _, _, _, _, _, _, _, _, _, _, _, _, _): return date case let .messageService(_, _, _, _, _, date, _, _): return date @@ -156,7 +156,7 @@ extension Api.Message { var preCachedResources: [(MediaResource, Data)]? { switch self { - case let .message(_, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _): return media?.preCachedResources default: return nil @@ -165,7 +165,7 @@ extension Api.Message { var preCachedStories: [StoryId: Api.StoryItem]? { switch self { - case let .message(_, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _): + case let .message(_, _, _, _, _, _, _, _, _, _, _, _, media, _, _, _, _, _, _, _, _, _, _, _, _): return media?.preCachedStories default: return nil diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/QuickReplyMessages.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/QuickReplyMessages.swift index a7e321c872..fcc57b2281 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/QuickReplyMessages.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/QuickReplyMessages.swift @@ -388,7 +388,7 @@ func _internal_sendMessageShortcut(account: Account, peerId: PeerId, id: Int32) guard let peer, let inputPeer = apiInputPeer(peer) else { return .complete() } - return account.network.request(Api.functions.messages.sendQuickReplyMessages(peer: inputPeer, shortcutId: id)) + return account.network.request(Api.functions.messages.sendQuickReplyMessages(peer: inputPeer, shortcutId: id, id: [], randomId: [])) |> map(Optional.init) |> `catch` { _ -> Signal in return .single(nil) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift index d0bc67b725..38876a16b8 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/TelegramEnginePeers.swift @@ -30,6 +30,59 @@ public final class OpaqueChatInterfaceState { } } +public final class TelegramCollectibleItemInfo: Equatable { + public enum Subject: Equatable { + case username(String) + case phoneNumber(String) + } + + public let subject: Subject + public let purchaseDate: Int32 + public let currency: String + public let currencyAmount: Int64 + public let cryptoCurrency: String + public let cryptoCurrencyAmount: Int64 + public let url: String + + public init(subject: Subject, purchaseDate: Int32, currency: String, currencyAmount: Int64, cryptoCurrency: String, cryptoCurrencyAmount: Int64, url: String) { + self.subject = subject + self.purchaseDate = purchaseDate + self.currency = currency + self.currencyAmount = currencyAmount + self.cryptoCurrency = cryptoCurrency + self.cryptoCurrencyAmount = cryptoCurrencyAmount + self.url = url + } + + public static func ==(lhs: TelegramCollectibleItemInfo, rhs: TelegramCollectibleItemInfo) -> Bool { + if lhs === rhs { + return true + } + if lhs.subject != rhs.subject { + return false + } + if lhs.purchaseDate != rhs.purchaseDate { + return false + } + if lhs.currency != rhs.currency { + return false + } + if lhs.currencyAmount != rhs.currencyAmount { + return false + } + if lhs.cryptoCurrency != rhs.cryptoCurrency { + return false + } + if lhs.cryptoCurrencyAmount != rhs.cryptoCurrencyAmount { + return false + } + if lhs.url != rhs.url { + return false + } + return true + } +} + public extension TelegramEngine { enum NextUnreadChannelLocation: Equatable { case same @@ -1387,6 +1440,56 @@ public extension TelegramEngine { }) }).start() } + + public func getCollectibleUsernameInfo(username: String) -> Signal { + return self.account.network.request(Api.functions.fragment.getCollectibleInfo(collectible: .inputCollectibleUsername(username: username))) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> map { result -> TelegramCollectibleItemInfo? in + guard let result else { + return nil + } + switch result { + case let .collectibleInfo(purchaseDate, currency, amount, cryptoCurrency, cryptoAmount, url): + return TelegramCollectibleItemInfo( + subject: .username(username), + purchaseDate: purchaseDate, + currency: currency, + currencyAmount: amount, + cryptoCurrency: cryptoCurrency, + cryptoCurrencyAmount: cryptoAmount, + url: url + ) + } + } + } + + public func getCollectiblePhoneNumberInfo(phoneNumber: String) -> Signal { + return self.account.network.request(Api.functions.fragment.getCollectibleInfo(collectible: .inputCollectiblePhone(phone: phoneNumber))) + |> map(Optional.init) + |> `catch` { _ -> Signal in + return .single(nil) + } + |> map { result -> TelegramCollectibleItemInfo? in + guard let result else { + return nil + } + switch result { + case let .collectibleInfo(purchaseDate, currency, amount, cryptoCurrency, cryptoAmount, url): + return TelegramCollectibleItemInfo( + subject: .phoneNumber(phoneNumber), + purchaseDate: purchaseDate, + currency: currency, + currencyAmount: amount, + cryptoCurrency: cryptoCurrency, + cryptoCurrencyAmount: cryptoAmount, + url: url + ) + } + } + } } } diff --git a/submodules/TelegramStringFormatting/Sources/CurrencyFormat.swift b/submodules/TelegramStringFormatting/Sources/CurrencyFormat.swift index 2986a87c58..faf6979c99 100644 --- a/submodules/TelegramStringFormatting/Sources/CurrencyFormat.swift +++ b/submodules/TelegramStringFormatting/Sources/CurrencyFormat.swift @@ -1,15 +1,15 @@ import Foundation import AppBundle -private final class CurrencyFormatterEntry { - let symbol: String - let thousandsSeparator: String - let decimalSeparator: String - let symbolOnLeft: Bool - let spaceBetweenAmountAndSymbol: Bool - let decimalDigits: Int +public final class CurrencyFormatterEntry { + public let symbol: String + public let thousandsSeparator: String + public let decimalSeparator: String + public let symbolOnLeft: Bool + public let spaceBetweenAmountAndSymbol: Bool + public let decimalDigits: Int - init(symbol: String, thousandsSeparator: String, decimalSeparator: String, symbolOnLeft: Bool, spaceBetweenAmountAndSymbol: Bool, decimalDigits: Int) { + public init(symbol: String, thousandsSeparator: String, decimalSeparator: String, symbolOnLeft: Bool, spaceBetweenAmountAndSymbol: Bool, decimalDigits: Int) { self.symbol = symbol self.thousandsSeparator = thousandsSeparator self.decimalSeparator = decimalSeparator @@ -191,8 +191,8 @@ public func formatCurrencyAmount(_ amount: Int64, currency: String) -> String { } } -public func formatCurrencyAmountCustom(_ amount: Int64, currency: String) -> (String, String, Bool) { - if let entry = currencyFormatterEntries[currency] ?? currencyFormatterEntries["USD"] { +public func formatCurrencyAmountCustom(_ amount: Int64, currency: String, customFormat: CurrencyFormatterEntry? = nil) -> (String, String, Bool) { + if let entry = customFormat ?? currencyFormatterEntries[currency] ?? currencyFormatterEntries["USD"] { var result = "" if amount < 0 { result.append("-") diff --git a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift index 8cdc962093..8483290226 100644 --- a/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift +++ b/submodules/TelegramStringFormatting/Sources/PresenceStrings.swift @@ -143,7 +143,6 @@ public func stringForCompactDate(timestamp: Int32, strings: PresentationStrings, var timeinfo: tm = tm() localtime_r(&t, &timeinfo) - //TODO:localize return "\(shortStringForDayOfWeek(strings: strings, day: timeinfo.tm_wday)) \(timeinfo.tm_mday) \(monthAtIndex(Int(timeinfo.tm_mon), strings: strings))" } diff --git a/submodules/TelegramUI/BUILD b/submodules/TelegramUI/BUILD index b8a93acb65..3ff80453f1 100644 --- a/submodules/TelegramUI/BUILD +++ b/submodules/TelegramUI/BUILD @@ -437,6 +437,7 @@ swift_library( "//submodules/TelegramUI/Components/Settings/BusinessHoursSetupScreen", "//submodules/TelegramUI/Components/Settings/AutomaticBusinessMessageSetupScreen", "//submodules/TelegramUI/Components/Settings/QuickReplyNameAlertController", + "//submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen" ] + select({ "@build_bazel_rules_apple//apple:ios_arm64": appcenter_targets, "//build-system:ios_sim_arm64": [], diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD index 9b1fd4efd9..becde7514e 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/BUILD @@ -140,6 +140,7 @@ swift_library( "//submodules/Components/MultilineTextComponent", "//submodules/TelegramUI/Components/Settings/PeerNameColorItem", "//submodules/TelegramUI/Components/PlainButtonComponent", + "//submodules/TelegramUI/Components/TextLoadingEffect", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift index 8093277652..0929d6f58f 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/ListItems/PeerInfoScreenLabeledValueItem.swift @@ -7,6 +7,8 @@ import UIKit import AppBundle import TelegramStringFormatting import ContextUI +import SwiftSignalKit +import TextLoadingEffect enum PeerInfoScreenLabeledValueTextColor { case primary @@ -22,6 +24,23 @@ enum PeerInfoScreenLabeledValueIcon { case qrCode } +private struct TextLinkItemSource: Equatable { + enum Target { + case primary + case additional + } + + let item: TextLinkItem + let target: Target + let range: NSRange? + + init(item: TextLinkItem, target: Target, range: NSRange?) { + self.item = item + self.target = target + self.range = range + } +} + final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem { let id: AnyHashable let label: String @@ -30,9 +49,9 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem { let textColor: PeerInfoScreenLabeledValueTextColor let textBehavior: PeerInfoScreenLabeledValueTextBehavior let icon: PeerInfoScreenLabeledValueIcon? - let action: ((ASDisplayNode) -> Void)? + let action: ((ASDisplayNode, Promise?) -> Void)? let longTapAction: ((ASDisplayNode) -> Void)? - let linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?) -> Void)? + let linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?, Promise?) -> Void)? let iconAction: (() -> Void)? let contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? let requestLayout: () -> Void @@ -45,9 +64,9 @@ final class PeerInfoScreenLabeledValueItem: PeerInfoScreenItem { textColor: PeerInfoScreenLabeledValueTextColor = .primary, textBehavior: PeerInfoScreenLabeledValueTextBehavior = .singleLine, icon: PeerInfoScreenLabeledValueIcon? = nil, - action: ((ASDisplayNode) -> Void)?, + action: ((ASDisplayNode, Promise?) -> Void)?, longTapAction: ((ASDisplayNode) -> Void)? = nil, - linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?) -> Void)? = nil, + linkItemAction: ((TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?, Promise?) -> Void)? = nil, iconAction: (() -> Void)? = nil, contextAction: ((ASDisplayNode, ContextGesture?, CGPoint?) -> Void)? = nil, requestLayout: @escaping () -> Void @@ -116,9 +135,14 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { private let activateArea: AccessibilityAreaNode + private var validLayout: (width: CGFloat, safeInsets: UIEdgeInsets, presentationData: PresentationData, item: PeerInfoScreenItem, topItem: PeerInfoScreenItem?, bottomItem: PeerInfoScreenItem?, hasCorners: Bool)? private var item: PeerInfoScreenLabeledValueItem? private var theme: PresentationTheme? + private var linkProgressView: TextLoadingEffectView? + private var linkItemWithProgress: TextLinkItemSource? + private var linkItemProgressDisposable: Disposable? + private var isExpanded: Bool = false override init() { @@ -259,6 +283,10 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { } } + deinit { + self.linkItemProgressDisposable?.dispose() + } + @objc private func expandPressed() { self.isExpanded = true self.item?.requestLayout() @@ -313,11 +341,57 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { case .tap, .longTap: if let item = self.item { if let linkItem = self.linkItemAtPoint(location) { - item.linkItemAction?(gesture == .tap ? .tap : .longTap, linkItem, self.linkHighlightingNode ?? self, self.linkHighlightingNode?.rects.first) + self.linkItemProgressDisposable?.dispose() + let progressValue = Promise(false) + self.linkItemProgressDisposable = (progressValue.get() + |> distinctUntilChanged + |> deliverOnMainQueue).start(next: { [weak self] value in + guard let self else { + return + } + var currentLinkItem: TextLinkItemSource? + if value { + currentLinkItem = linkItem + } + if self.linkItemWithProgress != currentLinkItem { + self.linkItemWithProgress = currentLinkItem + + if let validLayout = self.validLayout { + let _ = self.update(width: validLayout.width, safeInsets: validLayout.safeInsets, presentationData: validLayout.presentationData, item: validLayout.item, topItem: validLayout.topItem, bottomItem: validLayout.bottomItem, hasCorners: validLayout.hasCorners, transition: .immediate) + } + } + }) + + item.linkItemAction?(gesture == .tap ? .tap : .longTap, linkItem.item, self.linkHighlightingNode ?? self, self.linkHighlightingNode?.rects.first, progressValue) } else if case .longTap = gesture { item.longTapAction?(self) } else if case .tap = gesture { - item.action?(self.contextSourceNode) + var linkItem: TextLinkItemSource? + if let attributedText = self.textNode.attributedText { + linkItem = TextLinkItemSource(item: .url(url: "", concealed: false), target: .primary, range: NSRange(location: 0, length: attributedText.length)) + } + self.linkItemProgressDisposable?.dispose() + let progressValue = Promise(false) + self.linkItemProgressDisposable = (progressValue.get() + |> distinctUntilChanged + |> deliverOnMainQueue).start(next: { [weak self] value in + guard let self else { + return + } + var currentLinkItem: TextLinkItemSource? + if value { + currentLinkItem = linkItem + } + if self.linkItemWithProgress != currentLinkItem { + self.linkItemWithProgress = currentLinkItem + + if let validLayout = self.validLayout { + let _ = self.update(width: validLayout.width, safeInsets: validLayout.safeInsets, presentationData: validLayout.presentationData, item: validLayout.item, topItem: validLayout.topItem, bottomItem: validLayout.bottomItem, hasCorners: validLayout.hasCorners, transition: .immediate) + } + } + }) + + item.action?(self.contextSourceNode, progressValue) } } default: @@ -334,13 +408,15 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { return 10.0 } + self.validLayout = (width, safeInsets, presentationData, item, topItem, bottomItem, hasCorners) + self.item = item self.theme = presentationData.theme if let action = item.action { self.selectionNode.pressed = { [weak self] in if let strongSelf = self { - action(strongSelf.contextSourceNode) + action(strongSelf.contextSourceNode, nil) } } } else { @@ -553,30 +629,100 @@ private final class PeerInfoScreenLabeledValueItemNode: PeerInfoScreenItemNode { } self.contextSourceNode.contentRect = extractedRect + if let linkItemWithProgress = self.linkItemWithProgress, let range = linkItemWithProgress.range { + let linkProgressView: TextLoadingEffectView + if let current = self.linkProgressView { + linkProgressView = current + } else { + linkProgressView = TextLoadingEffectView(frame: CGRect()) + self.linkProgressView = linkProgressView + self.contextSourceNode.contentNode.view.addSubview(linkProgressView) + } + + let progressColor: UIColor = presentationData.theme.list.itemAccentColor.withMultipliedAlpha(0.1) + + let targetTextNode: TextNode + switch linkItemWithProgress.target { + case .primary: + targetTextNode = self.textNode + case .additional: + targetTextNode = self.additionalTextNode + } + linkProgressView.frame = targetTextNode.frame + linkProgressView.update(color: progressColor, textNode: targetTextNode, range: range) + } else { + if let linkProgressView = self.linkProgressView { + self.linkProgressView = nil + linkProgressView.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.2, removeOnCompletion: false, completion: { [weak linkProgressView] _ in + linkProgressView?.removeFromSuperview() + }) + } + } + return height } - private func linkItemAtPoint(_ point: CGPoint) -> TextLinkItem? { + private func linkItemAtPoint(_ point: CGPoint) -> TextLinkItemSource? { let textNodeFrame = self.textNode.frame - if let (_, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { + if let (index, attributes) = self.textNode.attributesAtPoint(CGPoint(x: point.x - textNodeFrame.minX, y: point.y - textNodeFrame.minY)) { + var item: TextLinkItem? + var urlRange: NSRange? if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { - return .url(url: url, concealed: false) + item = .url(url: url, concealed: false) + + if let (_, _, urlRangeValue) = self.textNode.attributeSubstringWithRange(name: TelegramTextAttributes.URL, index: index) { + urlRange = urlRangeValue + } } else if let peerName = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerTextMention)] as? String { - return .mention(peerName) + item = .mention(peerName) + + if let (_, _, urlRangeValue) = self.textNode.attributeSubstringWithRange(name: NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerTextMention).rawValue, index: index) { + urlRange = urlRangeValue + } } else if let hashtag = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag)] as? TelegramHashtag { - return .hashtag(hashtag.peerName, hashtag.hashtag) + item = .hashtag(hashtag.peerName, hashtag.hashtag) + + if let (_, _, urlRangeValue) = self.textNode.attributeSubstringWithRange(name: NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag).rawValue, index: index) { + urlRange = urlRangeValue + } + } else { + item = nil + } + if let item { + return TextLinkItemSource(item: item, target: .primary, range: urlRange) } else { return nil } } let additionalTextNodeFrame = self.additionalTextNode.frame - if let (_, attributes) = self.additionalTextNode.attributesAtPoint(CGPoint(x: point.x - additionalTextNodeFrame.minX, y: point.y - additionalTextNodeFrame.minY)) { + if let (index, attributes) = self.additionalTextNode.attributesAtPoint(CGPoint(x: point.x - additionalTextNodeFrame.minX, y: point.y - additionalTextNodeFrame.minY)) { + var item: TextLinkItem? + var urlRange: NSRange? + if let url = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.URL)] as? String { - return .url(url: url, concealed: false) + item = .url(url: url, concealed: false) + + if let (_, _, urlRangeValue) = self.additionalTextNode.attributeSubstringWithRange(name: TelegramTextAttributes.URL, index: index) { + urlRange = urlRangeValue + } } else if let peerName = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerTextMention)] as? String { - return .mention(peerName) + item = .mention(peerName) + + if let (_, _, urlRangeValue) = self.additionalTextNode.attributeSubstringWithRange(name: NSAttributedString.Key(rawValue: TelegramTextAttributes.PeerTextMention).rawValue, index: index) { + urlRange = urlRangeValue + } } else if let hashtag = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag)] as? TelegramHashtag { - return .hashtag(hashtag.peerName, hashtag.hashtag) + item = .hashtag(hashtag.peerName, hashtag.hashtag) + + if let (_, _, urlRangeValue) = self.additionalTextNode.attributeSubstringWithRange(name: NSAttributedString.Key(rawValue: TelegramTextAttributes.Hashtag).rawValue, index: index) { + urlRange = urlRangeValue + } + } else { + item = nil + } + + if let item { + return TextLinkItemSource(item: item, target: .additional, range: urlRange) } else { return nil } diff --git a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift index 74439e4e9f..4b28227d77 100644 --- a/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift +++ b/submodules/TelegramUI/Components/PeerInfo/PeerInfoScreen/Sources/PeerInfoScreen.swift @@ -531,7 +531,7 @@ private enum TopicsLimitedReason { private final class PeerInfoInteraction { let openChat: () -> Void - let openUsername: (String) -> Void + let openUsername: (String, Bool, Promise?) -> Void let openPhone: (String, ASDisplayNode, ContextGesture?) -> Void let editingOpenNotificationSettings: () -> Void let editingOpenSoundSettings: () -> Void @@ -585,7 +585,7 @@ private final class PeerInfoInteraction { let openEditing: () -> Void init( - openUsername: @escaping (String) -> Void, + openUsername: @escaping (String, Bool, Promise?) -> Void, openPhone: @escaping (String, ASDisplayNode, ContextGesture?) -> Void, editingOpenNotificationSettings: @escaping () -> Void, editingOpenSoundSettings: @escaping () -> Void, @@ -1092,7 +1092,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese let bioContextAction: (ASDisplayNode) -> Void = { sourceNode in interaction.openPeerInfoContextMenu(.bio, sourceNode, nil) } - let bioLinkAction: (TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?) -> Void = { action, item, _, _ in + let bioLinkAction: (TextLinkItemActionType, TextLinkItem, ASDisplayNode, CGRect?, Promise?) -> Void = { action, item, _, _, _ in interaction.performBioLinkAction(action, item) } @@ -1109,7 +1109,7 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese } else { label = presentationData.strings.ContactInfo_PhoneLabelMobile } - items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 2, label: label, text: formattedPhone, textColor: .accent, action: { node in + items[.peerInfo]!.append(PeerInfoScreenLabeledValueItem(id: 2, label: label, text: formattedPhone, textColor: .accent, action: { node, _ in interaction.openPhone(phone, node, nil) }, longTapAction: nil, contextAction: { node, gesture, _ in interaction.openPhone(phone, node, gesture) @@ -1132,14 +1132,14 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese additionalText: additionalUsernames, textColor: .accent, icon: .qrCode, - action: { _ in - interaction.openUsername(mainUsername) + action: { _, progress in + interaction.openUsername(mainUsername, true, progress) }, longTapAction: { sourceNode in interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil) - }, linkItemAction: { type, item, _, _ in + }, linkItemAction: { type, item, _, _, progress in if case .tap = type { if case let .mention(username) = item { - interaction.openUsername(String(username[username.index(username.startIndex, offsetBy: 1)...])) + interaction.openUsername(String(username[username.index(username.startIndex, offsetBy: 1)...]), false, progress) } } }, iconAction: { @@ -1307,14 +1307,14 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese text: linkText, textColor: .accent, icon: .qrCode, - action: { _ in - interaction.openUsername(linkText) + action: { _, progress in + interaction.openUsername(linkText, true, progress) }, longTapAction: { sourceNode in interaction.openPeerInfoContextMenu(.link(customLink: linkText), sourceNode, nil) - }, linkItemAction: { type, item, _, _ in + }, linkItemAction: { type, item, _, _, progress in if case .tap = type { if case let .mention(username) = item { - interaction.openUsername(String(username.suffix(from: username.index(username.startIndex, offsetBy: 1)))) + interaction.openUsername(String(username.suffix(from: username.index(username.startIndex, offsetBy: 1))), false, progress) } } }, iconAction: { @@ -1360,14 +1360,14 @@ private func infoItems(data: PeerInfoScreenData?, context: AccountContext, prese additionalText: additionalUsernames, textColor: .accent, icon: .qrCode, - action: { _ in - interaction.openUsername(mainUsername) + action: { _, progress in + interaction.openUsername(mainUsername, true, progress) }, longTapAction: { sourceNode in interaction.openPeerInfoContextMenu(.link(customLink: nil), sourceNode, nil) - }, linkItemAction: { type, item, sourceNode, sourceRect in + }, linkItemAction: { type, item, sourceNode, sourceRect, progress in if case .tap = type { if case let .mention(username) = item { - interaction.openUsername(String(username.suffix(from: username.index(username.startIndex, offsetBy: 1)))) + interaction.openUsername(String(username.suffix(from: username.index(username.startIndex, offsetBy: 1))), false, progress) } } else if case .longTap = type { if case let .mention(username) = item { @@ -2393,8 +2393,8 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro self.paneContainerNode.parentController = controller self._interaction = PeerInfoInteraction( - openUsername: { [weak self] value in - self?.openUsername(value: value) + openUsername: { [weak self] value, isMainUsername, progress in + self?.openUsername(value: value, isMainUsername: isMainUsername, progress: progress) }, openPhone: { [weak self] value, node, gesture in self?.openPhone(value: value, node: node, gesture: gesture) @@ -6416,7 +6416,7 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro contextController.pushItems(items: .single(ContextController.Items(content: .list(subItems)))) } - private func openUsername(value: String) { + private func openUsername(value: String, isMainUsername: Bool, progress: Promise?) { let url: String if value.hasPrefix("https://") { url = value @@ -6424,70 +6424,101 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro url = "https://t.me/\(value)" } - let shareController = ShareController(context: self.context, subject: .url(url), updatedPresentationData: self.controller?.updatedPresentationData) - shareController.completed = { [weak self] peerIds in - guard let strongSelf = self else { + let openShare: (TelegramCollectibleItemInfo?) -> Void = { [weak self] collectibleItemInfo in + guard let self else { return } - let _ = (strongSelf.context.engine.data.get( - EngineDataList( - peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init) - ) - ) - |> deliverOnMainQueue).startStandalone(next: { [weak self] peerList in + let shareController = ShareController(context: self.context, subject: .url(url), updatedPresentationData: self.controller?.updatedPresentationData, collectibleItemInfo: collectibleItemInfo) + shareController.completed = { [weak self] peerIds in guard let strongSelf = self else { return } - - let peers = peerList.compactMap { $0 } - let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } - - let text: String - var savedMessages = false - if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId { - text = presentationData.strings.UserInfo_LinkForwardTooltip_SavedMessages_One - savedMessages = true - } else { - if peers.count == 1, let peer = peers.first { - let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - text = presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peerName).string - } else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last { - let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - text = presentationData.strings.UserInfo_LinkForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string - } else if let peer = peers.first { - let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - text = presentationData.strings.UserInfo_LinkForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string - } else { - text = "" + let _ = (strongSelf.context.engine.data.get( + EngineDataList( + peerIds.map(TelegramEngine.EngineData.Item.Peer.Peer.init) + ) + ) + |> deliverOnMainQueue).startStandalone(next: { [weak self] peerList in + guard let strongSelf = self else { + return } + + let peers = peerList.compactMap { $0 } + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } + + let text: String + var savedMessages = false + if peerIds.count == 1, let peerId = peerIds.first, peerId == strongSelf.context.account.peerId { + text = presentationData.strings.UserInfo_LinkForwardTooltip_SavedMessages_One + savedMessages = true + } else { + if peers.count == 1, let peer = peers.first { + let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + text = presentationData.strings.UserInfo_LinkForwardTooltip_Chat_One(peerName).string + } else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last { + let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : firstPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : secondPeer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + text = presentationData.strings.UserInfo_LinkForwardTooltip_TwoChats_One(firstPeerName, secondPeerName).string + } else if let peer = peers.first { + let peerName = peer.displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + text = presentationData.strings.UserInfo_LinkForwardTooltip_ManyChats_One(peerName, "\(peers.count - 1)").string + } else { + text = "" + } + } + + strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in + if savedMessages, let self, action == .info { + let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) + |> deliverOnMainQueue).start(next: { [weak self] peer in + guard let self, let peer else { + return + } + guard let navigationController = self.controller?.navigationController as? NavigationController else { + return + } + self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), forceOpenChat: true)) + }) + } + return false + }), in: .current) + }) + } + shareController.actionCompleted = { [weak self] in + 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: .current) + } + } + self.view.endEditing(true) + self.controller?.present(shareController, in: .window(.root)) + } + + if let pathComponents = URL(string: url)?.pathComponents, pathComponents.count >= 2, !pathComponents[1].isEmpty { + let namePart = pathComponents[1] + progress?.set(.single(true)) + let _ = (self.context.sharedContext.makeCollectibleItemInfoScreenInitialData(context: self.context, peerId: self.peerId, subject: .username(namePart)) + |> deliverOnMainQueue).start(next: { [weak self] initialData in + guard let self else { + return } - strongSelf.controller?.present(UndoOverlayController(presentationData: presentationData, content: .forward(savedMessages: savedMessages, text: text), elevatedLayout: false, animateInAsReplacement: true, action: { action in - if savedMessages, let self, action == .info { - let _ = (self.context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: self.context.account.peerId)) - |> deliverOnMainQueue).start(next: { [weak self] peer in - guard let self, let peer else { - return - } - guard let navigationController = self.controller?.navigationController as? NavigationController else { - return - } - self.context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: self.context, chatLocation: .peer(peer), forceOpenChat: true)) - }) + progress?.set(.single(false)) + + if let initialData { + if isMainUsername { + openShare(initialData.collectibleItemInfo) + } else { + self.view.endEditing(true) + self.controller?.push(self.context.sharedContext.makeCollectibleItemInfoScreen(context: self.context, initialData: initialData)) } - return false - }), in: .current) + } else { + openShare(nil) + } }) + } else { + openShare(nil) } - shareController.actionCompleted = { [weak self] in - 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: .current) - } - } - self.view.endEditing(true) - self.controller?.present(shareController, in: .window(.root)) } private func requestCall(isVideo: Bool, gesture: ContextGesture? = nil, contextController: ContextControllerProtocol? = nil, result: ((ContextMenuActionResult) -> Void)? = nil, backAction: ((ContextControllerProtocol) -> Void)? = nil) { @@ -6697,10 +6728,27 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro } var actions = ContextController.Items(content: .list(items)) if isAnonymousNumber && !accountIsFromUS { + let collectibleInfo = Promise() + collectibleInfo.set(strongSelf.context.sharedContext.makeCollectibleItemInfoScreenInitialData(context: strongSelf.context, peerId: strongSelf.peerId, subject: .phoneNumber(value))) + actions.tip = .animatedEmoji(text: strongSelf.presentationData.strings.UserInfo_AnonymousNumberInfo, arguments: nil, file: nil, action: { [weak self] in - if let strongSelf = self { - strongSelf.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: "https://fragment.com/numbers", forceExternal: true, presentationData: strongSelf.presentationData, navigationController: nil, dismissInput: {}) + guard let self else { + return } + + let _ = (collectibleInfo.get() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] initialData in + guard let self else { + return + } + if let initialData { + self.view.endEditing(true) + self.controller?.push(self.context.sharedContext.makeCollectibleItemInfoScreen(context: self.context, initialData: initialData)) + } else { + self.context.sharedContext.openExternalUrl(context: strongSelf.context, urlContext: .generic, url: "https://fragment.com/numbers", forceExternal: true, presentationData: self.presentationData, navigationController: nil, dismissInput: {}) + } + }) }) } let contextController = ContextController(presentationData: strongSelf.presentationData, source: .extracted(PeerInfoContextExtractedContentSource(sourceNode: sourceNode)), items: .single(actions), gesture: gesture) diff --git a/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/BUILD b/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/BUILD new file mode 100644 index 0000000000..7a12d1fc72 --- /dev/null +++ b/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/BUILD @@ -0,0 +1,40 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "CollectibleItemInfoScreen", + module_name = "CollectibleItemInfoScreen", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/AsyncDisplayKit", + "//submodules/Display", + "//submodules/Postbox", + "//submodules/TelegramCore", + "//submodules/SSignalKit/SwiftSignalKit", + "//submodules/ComponentFlow", + "//submodules/Components/ViewControllerComponent", + "//submodules/Components/ComponentDisplayAdapters", + "//submodules/Components/MultilineTextComponent", + "//submodules/Components/BalancedTextComponent", + "//submodules/TelegramPresentationData", + "//submodules/AccountContext", + "//submodules/AppBundle", + "//submodules/Components/SheetComponent", + "//submodules/PresentationDataUtils", + "//submodules/Components/SolidRoundedButtonComponent", + "//submodules/Components/BundleIconComponent", + "//submodules/TelegramUI/Components/ButtonComponent", + "//submodules/TelegramUI/Components/PlainButtonComponent", + "//submodules/Markdown", + "//submodules/TelegramStringFormatting", + "//submodules/AvatarNode", + "//submodules/PhoneNumberFormat", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/Sources/CollectibleItemInfoScreen.swift b/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/Sources/CollectibleItemInfoScreen.swift new file mode 100644 index 0000000000..df6c8248b0 --- /dev/null +++ b/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/Sources/CollectibleItemInfoScreen.swift @@ -0,0 +1,772 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import ViewControllerComponent +import AccountContext +import SheetComponent +import ButtonComponent +import PlainButtonComponent +import TelegramCore +import SwiftSignalKit +import MultilineTextComponent +import BalancedTextComponent +import TelegramStringFormatting +import AvatarNode +import TelegramPresentationData +import PhoneNumberFormat +import BundleIconComponent + +private final class PeerBadgeComponent: Component { + let context: AccountContext + let theme: PresentationTheme + let strings: PresentationStrings + let peer: EnginePeer + + init( + context: AccountContext, + theme: PresentationTheme, + strings: PresentationStrings, + peer: EnginePeer + ) { + self.context = context + self.theme = theme + self.strings = strings + self.peer = peer + } + + static func ==(lhs: PeerBadgeComponent, rhs: PeerBadgeComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + if lhs.theme !== rhs.theme { + return false + } + if lhs.strings !== rhs.strings { + return false + } + if lhs.peer != rhs.peer { + return false + } + return true + } + + final class View: UIView { + private let background = ComponentView() + private let title = ComponentView() + private var avatarNode: AvatarNode? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: PeerBadgeComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + let height: CGFloat = 32.0 + let avatarPadding: CGFloat = 1.0 + + let avatarDiameter = height - avatarPadding * 2.0 + let avatarTextSpacing: CGFloat = 4.0 + let rightTextInset: CGFloat = 12.0 + + let titleSize = self.title.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: component.peer.displayTitle(strings: component.strings, displayOrder: .firstLast), font: Font.medium(15.0), textColor: component.theme.list.itemPrimaryTextColor)) + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - avatarPadding - avatarDiameter - avatarTextSpacing - rightTextInset, height: height) + ) + let titleFrame = CGRect(origin: CGPoint(x: avatarPadding + avatarDiameter + avatarTextSpacing, y: floorToScreenPixels((height - titleSize.height) * 0.5)), size: titleSize) + if let titleView = self.title.view { + if titleView.superview == nil { + self.addSubview(titleView) + } + titleView.frame = titleFrame + } + + let avatarNode: AvatarNode + if let current = self.avatarNode { + avatarNode = current + } else { + avatarNode = AvatarNode(font: avatarPlaceholderFont(size: 15.0)) + self.avatarNode = avatarNode + self.addSubview(avatarNode.view) + } + + let avatarFrame = CGRect(origin: CGPoint(x: avatarPadding, y: avatarPadding), size: CGSize(width: avatarDiameter, height: avatarDiameter)) + avatarNode.frame = avatarFrame + avatarNode.updateSize(size: avatarFrame.size) + avatarNode.setPeer(context: component.context, theme: component.theme, peer: component.peer) + + let size = CGSize(width: avatarPadding + avatarDiameter + avatarTextSpacing + titleSize.width + rightTextInset, height: height) + + let _ = self.background.update( + transition: transition, + component: AnyComponent(RoundedRectangle(color: component.theme.list.itemPrimaryTextColor.withMultipliedAlpha(0.1), cornerRadius: nil)), + environment: {}, + containerSize: size + ) + if let backgroundView = self.background.view { + if backgroundView.superview == nil { + self.insertSubview(backgroundView, at: 0) + } + transition.setFrame(view: backgroundView, frame: CGRect(origin: CGPoint(), size: size)) + } + + 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) + } +} + +private final class CollectibleItemInfoScreenContentComponent: Component { + typealias EnvironmentType = ViewControllerComponentContainer.Environment + + let context: AccountContext + let initialData: CollectibleItemInfoScreen.InitialData + let dismiss: () -> Void + + init( + context: AccountContext, + initialData: CollectibleItemInfoScreen.InitialData, + dismiss: @escaping () -> Void + ) { + self.context = context + self.initialData = initialData + self.dismiss = dismiss + } + + static func ==(lhs: CollectibleItemInfoScreenContentComponent, rhs: CollectibleItemInfoScreenContentComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + return true + } + + final class View: UIView { + private let iconBackground = ComponentView() + private let icon = ComponentView() + private let title = ComponentView() + private let peerBadge = ComponentView() + private let text = ComponentView() + private let button = ComponentView() + private let copyButton = ComponentView() + + private var component: CollectibleItemInfoScreenContentComponent? + + private var currencySymbolIcon: UIImage? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: CollectibleItemInfoScreenContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.component = component + + let environment = environment[EnvironmentType.self].value + + let sideInset: CGFloat = 16.0 + let contentSideInset: CGFloat = sideInset + 16.0 + + var contentHeight: CGFloat = 0.0 + contentHeight += 30.0 + + let iconBackgroundSize = self.iconBackground.update( + transition: transition, + component: AnyComponent(RoundedRectangle(color: environment.theme.list.itemCheckColors.fillColor, cornerRadius: nil)), + environment: {}, + containerSize: CGSize(width: 90.0, height: 90.0) + ) + let iconBackgroundFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconBackgroundSize.width) * 0.5), y: contentHeight), size: iconBackgroundSize) + if let iconBackgroundView = self.iconBackground.view { + if iconBackgroundView.superview == nil { + self.addSubview(iconBackgroundView) + } + transition.setFrame(view: iconBackgroundView, frame: iconBackgroundFrame) + } + contentHeight += iconBackgroundSize.height + contentHeight += 16.0 + + let iconSize = self.icon.update( + transition: transition, + component: AnyComponent(BundleIconComponent( + name: "Peer Info/CollectibleUsernameInfoTitleIcon", + tintColor: environment.theme.list.itemCheckColors.foregroundColor + )), + environment: {}, + containerSize: iconBackgroundFrame.size + ) + let iconFrame = CGRect(origin: CGPoint(x: iconBackgroundFrame.minX + floor((iconBackgroundFrame.width - iconSize.width) * 0.5), y: iconBackgroundFrame.minY + floor((iconBackgroundFrame.height - iconSize.height) * 0.5)), size: iconSize) + if let iconView = self.icon.view { + if iconView.superview == nil { + self.addSubview(iconView) + } + transition.setFrame(view: iconView, frame: iconFrame) + } + + let titleText = NSMutableAttributedString() + let textText = NSMutableAttributedString() + switch component.initialData.subject { + case let .username(username): + let rawTitleString = environment.strings.CollectibleItemInfo_UsernameTitle("@\(username.username)") + titleText.append(NSAttributedString(string: rawTitleString.string, font: Font.semibold(16.0), textColor: environment.theme.list.itemPrimaryTextColor)) + for range in rawTitleString.ranges { + titleText.addAttributes([ + .foregroundColor: environment.theme.list.itemAccentColor, + NSAttributedString.Key(rawValue: "URL"): "" + ], range: range.range) + } + + let dateText = stringForDate(timestamp: username.info.purchaseDate, strings: environment.strings) + + let (rawCryptoCurrencyText, cryptoCurrencySign, _) = formatCurrencyAmountCustom(username.info.cryptoCurrencyAmount, currency: username.info.cryptoCurrency, customFormat: CurrencyFormatterEntry( + symbol: "~", + thousandsSeparator: ",", + decimalSeparator: ".", + symbolOnLeft: true, + spaceBetweenAmountAndSymbol: false, + decimalDigits: 9 + )) + var cryptoCurrencyText = rawCryptoCurrencyText + while cryptoCurrencyText.hasSuffix("0") { + cryptoCurrencyText = String(cryptoCurrencyText[cryptoCurrencyText.startIndex ..< cryptoCurrencyText.index(before: cryptoCurrencyText.endIndex)]) + } + if cryptoCurrencyText.hasSuffix(".") { + cryptoCurrencyText = String(cryptoCurrencyText[cryptoCurrencyText.startIndex ..< cryptoCurrencyText.index(before: cryptoCurrencyText.endIndex)]) + } + + let (currencyText, currencySign, _) = formatCurrencyAmountCustom(username.info.currencyAmount, currency: username.info.currency) + + let rawTextString = environment.strings.CollectibleItemInfo_UsernameText("@\(username.username)", environment.strings.CollectibleItemInfo_StoreName, dateText, "\(cryptoCurrencySign)\(cryptoCurrencyText)", "\(currencySign)\(currencyText)") + textText.append(NSAttributedString(string: rawTextString.string, font: Font.regular(15.0), textColor: environment.theme.list.itemPrimaryTextColor)) + for range in rawTextString.ranges { + switch range.index { + case 0: + textText.addAttribute(.font, value: Font.semibold(15.0), range: range.range) + case 1: + textText.addAttribute(.font, value: Font.semibold(15.0), range: range.range) + case 3: + textText.addAttribute(.font, value: Font.semibold(15.0), range: range.range) + default: + break + } + } + case let .phoneNumber(phoneNumber): + let formattedPhoneNumber = formatPhoneNumber(context: component.context, number: phoneNumber.phoneNumber) + + let rawTitleString = environment.strings.CollectibleItemInfo_PhoneTitle("\(formattedPhoneNumber)") + titleText.append(NSAttributedString(string: rawTitleString.string, font: Font.semibold(16.0), textColor: environment.theme.list.itemPrimaryTextColor)) + for range in rawTitleString.ranges { + titleText.addAttributes([ + .foregroundColor: environment.theme.list.itemAccentColor, + NSAttributedString.Key(rawValue: "URL"): "" + ], range: range.range) + } + + let dateText = stringForDate(timestamp: phoneNumber.info.purchaseDate, strings: environment.strings) + + let (rawCryptoCurrencyText, cryptoCurrencySign, _) = formatCurrencyAmountCustom(phoneNumber.info.cryptoCurrencyAmount, currency: phoneNumber.info.cryptoCurrency, customFormat: CurrencyFormatterEntry( + symbol: "~", + thousandsSeparator: ",", + decimalSeparator: ".", + symbolOnLeft: true, + spaceBetweenAmountAndSymbol: false, + decimalDigits: 9 + )) + var cryptoCurrencyText = rawCryptoCurrencyText + while cryptoCurrencyText.hasSuffix("0") { + cryptoCurrencyText = String(cryptoCurrencyText[cryptoCurrencyText.startIndex ..< cryptoCurrencyText.index(before: cryptoCurrencyText.endIndex)]) + } + if cryptoCurrencyText.hasSuffix(".") { + cryptoCurrencyText = String(cryptoCurrencyText[cryptoCurrencyText.startIndex ..< cryptoCurrencyText.index(before: cryptoCurrencyText.endIndex)]) + } + + let (currencyText, currencySign, _) = formatCurrencyAmountCustom(phoneNumber.info.currencyAmount, currency: phoneNumber.info.currency) + + let rawTextString = environment.strings.CollectibleItemInfo_PhoneText("\(formattedPhoneNumber)", environment.strings.CollectibleItemInfo_StoreName, dateText, "\(cryptoCurrencySign)\(cryptoCurrencyText)", "\(currencySign)\(currencyText)") + textText.append(NSAttributedString(string: rawTextString.string, font: Font.regular(15.0), textColor: environment.theme.list.itemPrimaryTextColor)) + for range in rawTextString.ranges { + switch range.index { + case 0: + textText.addAttribute(.font, value: Font.semibold(15.0), range: range.range) + case 1: + textText.addAttribute(.font, value: Font.semibold(15.0), range: range.range) + case 3: + textText.addAttribute(.font, value: Font.semibold(15.0), range: range.range) + default: + break + } + } + } + + let currencySymbolRange = (textText.string as NSString).range(of: "~") + + if self.currencySymbolIcon == nil { + if let templateImage = UIImage(bundleImageName: "Peer Info/CollectibleTonSymbolInline") { + self.currencySymbolIcon = generateImage(CGSize(width: templateImage.size.width, height: templateImage.size.height + 2.0), contextGenerator: { size, context in + context.clear(CGRect(origin: CGPoint(), size: size)) + if let cgImage = templateImage.cgImage { + context.draw(cgImage, in: CGRect(origin: CGPoint(x: 0.0, y: 2.0), size: templateImage.size)) + } + })?.withRenderingMode(.alwaysTemplate) + } + } + + if currencySymbolRange.location != NSNotFound, let currencySymbolIcon = self.currencySymbolIcon { + textText.replaceCharacters(in: currencySymbolRange, with: "$") + textText.addAttribute(.attachment, value: currencySymbolIcon, range: currencySymbolRange) + + 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 + } + } + let font = Font.semibold(15.0) + let runDelegateData = RunDelegateData( + ascent: font.ascender, + descent: font.descender, + width: currencySymbolIcon.size.width + 4.0 + ) + var callbacks = CTRunDelegateCallbacks( + version: kCTRunDelegateCurrentVersion, + dealloc: { dataRef in + Unmanaged.fromOpaque(dataRef).release() + }, + getAscent: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().ascent + }, + getDescent: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().descent + }, + getWidth: { dataRef in + let data = Unmanaged.fromOpaque(dataRef) + return data.takeUnretainedValue().width + } + ) + + if let runDelegate = CTRunDelegateCreate(&callbacks, Unmanaged.passRetained(runDelegateData).toOpaque()) { + textText.addAttribute(NSAttributedString.Key(rawValue: kCTRunDelegateAttributeName as String), value: runDelegate, range: currencySymbolRange) + } + } + + let titleSize = self.title.update( + transition: .immediate, + component: AnyComponent(BalancedTextComponent( + text: .plain(titleText), + horizontalAlignment: .center, + maximumNumberOfLines: 0, + lineSpacing: 0.185 + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - contentSideInset * 2.0, height: 1000.0) + ) + let titleFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: contentHeight), size: titleSize) + if let titleView = self.title.view { + if titleView.superview == nil { + self.addSubview(titleView) + } + transition.setPosition(view: titleView, position: titleFrame.center) + titleView.bounds = CGRect(origin: CGPoint(), size: titleFrame.size) + } + contentHeight += titleSize.height + contentHeight += 7.0 + + if let peer = component.initialData.peer { + let peerBadgeSize = self.peerBadge.update( + transition: transition, + component: AnyComponent(PeerBadgeComponent( + context: component.context, + theme: environment.theme, + strings: environment.strings, + peer: peer + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - contentSideInset * 2.0, height: 1000.0) + ) + let peerBadgeFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - peerBadgeSize.width) * 0.5), y: contentHeight), size: peerBadgeSize) + if let peerBadgeView = self.peerBadge.view { + if peerBadgeView.superview == nil { + self.addSubview(peerBadgeView) + } + transition.setFrame(view: peerBadgeView, frame: peerBadgeFrame) + } + contentHeight += peerBadgeSize.height + contentHeight += 23.0 + } + + let textSize = self.text.update( + transition: .immediate, + component: AnyComponent(BalancedTextComponent( + text: .plain(textText), + horizontalAlignment: .center, + maximumNumberOfLines: 0, + lineSpacing: 0.185 + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - contentSideInset * 2.0, height: 1000.0) + ) + let textFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - textSize.width) * 0.5), y: contentHeight), size: textSize) + if let textView = self.text.view { + if textView.superview == nil { + self.addSubview(textView) + } + transition.setPosition(view: textView, position: textFrame.center) + textView.bounds = CGRect(origin: CGPoint(), size: textFrame.size) + } + contentHeight += textSize.height + contentHeight += 21.0 + + let buttonSize = self.button.update( + transition: transition, + component: AnyComponent(ButtonComponent( + background: ButtonComponent.Background( + color: environment.theme.list.itemCheckColors.fillColor, + foreground: environment.theme.list.itemCheckColors.foregroundColor, + pressedColor: environment.theme.list.itemCheckColors.fillColor.withMultipliedAlpha(0.8) + ), + content: AnyComponentWithIdentity(id: AnyHashable(0 as Int), component: AnyComponent( + Text(text: environment.strings.CollectibleItemInfo_ButtonOpenInfo, font: Font.semibold(17.0), color: environment.theme.list.itemCheckColors.foregroundColor) + )), + isEnabled: true, + displaysProgress: false, + action: { [weak self] in + guard let self, let component = self.component else { + return + } + + switch component.initialData.subject { + case let .username(username): + component.context.sharedContext.applicationBindings.openUrl(username.info.url) + case let .phoneNumber(phoneNumber): + component.context.sharedContext.applicationBindings.openUrl(phoneNumber.info.url) + } + + component.dismiss() + } + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0) + ) + let buttonFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: buttonSize) + if let buttonView = self.button.view { + if buttonView.superview == nil { + self.addSubview(buttonView) + } + transition.setFrame(view: buttonView, frame: buttonFrame) + } + contentHeight += buttonSize.height + contentHeight += 5.0 + + let copyButtonTitle: String + switch component.initialData.subject { + case .username: + copyButtonTitle = environment.strings.CollectibleItemInfo_ButtonCopyUsername + case .phoneNumber: + copyButtonTitle = environment.strings.CollectibleItemInfo_ButtonCopyPhone + } + + + let copyButtonSize = self.copyButton.update( + transition: transition, + component: AnyComponent(PlainButtonComponent( + content: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: copyButtonTitle, font: Font.regular(17.0), textColor: environment.theme.list.itemAccentColor)) + )), + background: nil, + effectAlignment: .center, + minSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0), + contentInsets: UIEdgeInsets(), + action: { [weak self] in + guard let self, let component = self.component else { + return + } + + switch component.initialData.subject { + case let .username(username): + UIPasteboard.general.string = "https://t.me/\(username.username)" + case let .phoneNumber(phoneNumber): + let formattedPhoneNumber = formatPhoneNumber(context: component.context, number: phoneNumber.phoneNumber) + UIPasteboard.general.string = formattedPhoneNumber + } + + component.dismiss() + }, + isEnabled: true, + animateAlpha: true, + animateScale: false, + animateContents: false + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 50.0) + ) + let copyButtonFrame = CGRect(origin: CGPoint(x: sideInset, y: contentHeight), size: copyButtonSize) + if let copyButtonView = self.copyButton.view { + if copyButtonView.superview == nil { + self.addSubview(copyButtonView) + } + transition.setFrame(view: copyButtonView, frame: copyButtonFrame) + } + contentHeight += copyButtonSize.height - 9.0 + + if environment.safeInsets.bottom.isZero { + contentHeight += 16.0 + } else { + contentHeight += environment.safeInsets.bottom + 14.0 + } + + return CGSize(width: availableSize.width, height: contentHeight) + } + } + + 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) + } +} + +private final class CollectibleItemInfoScreenComponent: Component { + typealias EnvironmentType = ViewControllerComponentContainer.Environment + + let context: AccountContext + let initialData: CollectibleItemInfoScreen.InitialData + + init( + context: AccountContext, + initialData: CollectibleItemInfoScreen.InitialData + ) { + self.context = context + self.initialData = initialData + } + + static func ==(lhs: CollectibleItemInfoScreenComponent, rhs: CollectibleItemInfoScreenComponent) -> Bool { + if lhs.context !== rhs.context { + return false + } + return true + } + + final class View: UIView { + private let sheet = ComponentView<(ViewControllerComponentContainer.Environment, SheetComponentEnvironment)>() + private let sheetAnimateOut = ActionSlot>() + + private var component: CollectibleItemInfoScreenComponent? + private var environment: EnvironmentType? + + override init(frame: CGRect) { + super.init(frame: frame) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: CollectibleItemInfoScreenComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.component = component + + let environment = environment[ViewControllerComponentContainer.Environment.self].value + self.environment = environment + + let sheetEnvironment = SheetComponentEnvironment( + isDisplaying: environment.isVisible, + isCentered: environment.metrics.widthClass == .regular, + hasInputHeight: !environment.inputHeight.isZero, + regularMetricsSize: CGSize(width: 430.0, height: 900.0), + dismiss: { [weak self] _ in + guard let self, let environment = self.environment else { + return + } + self.sheetAnimateOut.invoke(Action { _ in + if let controller = environment.controller() { + controller.dismiss(completion: nil) + } + }) + } + ) + let _ = self.sheet.update( + transition: transition, + component: AnyComponent(SheetComponent( + content: AnyComponent(CollectibleItemInfoScreenContentComponent( + context: component.context, + initialData: component.initialData, + dismiss: { [weak self] in + guard let self else { + return + } + self.sheetAnimateOut.invoke(Action { [weak self] _ in + if let controller = environment.controller() { + controller.dismiss(completion: nil) + } + + guard let self else { + return + } + //TODO:open info + let _ = self + }) + } + )), + backgroundColor: .color(environment.theme.list.plainBackgroundColor), + animateOut: self.sheetAnimateOut + )), + environment: { + environment + sheetEnvironment + }, + containerSize: availableSize + ) + if let sheetView = self.sheet.view { + if sheetView.superview == nil { + self.addSubview(sheetView) + } + transition.setFrame(view: sheetView, frame: CGRect(origin: CGPoint(), size: availableSize)) + } + + 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) + } +} + +public class CollectibleItemInfoScreen: ViewControllerComponentContainer { + fileprivate enum ResolvedSubject { + struct Username { + var username: String + var info: TelegramCollectibleItemInfo + + init(username: String, info: TelegramCollectibleItemInfo) { + self.username = username + self.info = info + } + } + + struct PhoneNumber { + var phoneNumber: String + var info: TelegramCollectibleItemInfo + + init(phoneNumber: String, info: TelegramCollectibleItemInfo) { + self.phoneNumber = phoneNumber + self.info = info + } + } + + case username(Username) + case phoneNumber(PhoneNumber) + } + + public final class InitialData: CollectibleItemInfoScreenInitialData { + fileprivate let peer: EnginePeer? + fileprivate let subject: ResolvedSubject + + fileprivate init(peer: EnginePeer?, subject: ResolvedSubject) { + self.peer = peer + self.subject = subject + } + + public var collectibleItemInfo: TelegramCollectibleItemInfo { + switch self.subject { + case let .username(username): + return username.info + case let .phoneNumber(phoneNumber): + return phoneNumber.info + } + } + } + + public init(context: AccountContext, initialData: InitialData) { + super.init(context: context, component: CollectibleItemInfoScreenComponent( + context: context, + initialData: initialData + ), navigationBarAppearance: .none) + + self.statusBar.statusBarStyle = .Ignore + self.navigationPresentation = .flatModal + self.blocksBackgroundWhenInOverlay = true + } + + required public init(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public static func initialData(context: AccountContext, peerId: EnginePeer.Id, subject: CollectibleItemInfoScreenSubject) -> Signal { + switch subject { + case let .username(username): + return combineLatest( + context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + ), + context.engine.peers.getCollectibleUsernameInfo(username: username) + ) + |> map { peer, result -> CollectibleItemInfoScreenInitialData? in + guard let result else { + return nil + } + return InitialData(peer: peer, subject: .username(ResolvedSubject.Username( + username: username, + info: result + ))) + } + case let .phoneNumber(phoneNumber): + return combineLatest( + context.engine.data.get( + TelegramEngine.EngineData.Item.Peer.Peer(id: peerId) + ), + context.engine.peers.getCollectiblePhoneNumberInfo(phoneNumber: phoneNumber) + ) + |> map { peer, result -> CollectibleItemInfoScreenInitialData? in + guard let result else { + return nil + } + return InitialData(peer: peer, subject: .phoneNumber(ResolvedSubject.PhoneNumber( + phoneNumber: phoneNumber, + info: result + ))) + } + } + } + + deinit { + } + + override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { + super.containerLayoutUpdated(layout, transition: transition) + } + + override public func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + self.view.disablesInteractiveModalDismiss = true + } +} diff --git a/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/Sources/CollectibleItemInfoScreenContentComponent.swift b/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/Sources/CollectibleItemInfoScreenContentComponent.swift new file mode 100644 index 0000000000..288cbffad0 --- /dev/null +++ b/submodules/TelegramUI/Components/Settings/CollectibleItemInfoScreen/Sources/CollectibleItemInfoScreenContentComponent.swift @@ -0,0 +1,333 @@ +import Foundation +import UIKit +import Display +import ComponentFlow +import MultilineTextComponent +import TelegramPresentationData +import AppBundle +import BundleIconComponent +import Markdown +import TelegramCore + +/*public final class CollectibleItemInfoScreenContentComponent: Component { + public let theme: PresentationTheme + public let strings: PresentationStrings + public let settings: GlobalPrivacySettings + public let openSettings: () -> Void + + public init( + theme: PresentationTheme, + strings: PresentationStrings, + settings: GlobalPrivacySettings, + openSettings: @escaping () -> Void + ) { + self.theme = theme + self.strings = strings + self.settings = settings + self.openSettings = openSettings + } + + public static func ==(lhs: CollectibleItemInfoScreenContentComponent, rhs: CollectibleItemInfoScreenContentComponent) -> Bool { + if lhs.theme !== rhs.theme { + return false + } + if lhs.strings !== rhs.strings { + return false + } + if lhs.settings != rhs.settings { + return false + } + return true + } + + private final class Item { + let icon = ComponentView() + let title = ComponentView() + let text = ComponentView() + + init() { + } + } + + public final class View: UIView { + private let scrollView: UIScrollView + private let iconBackground: UIImageView + private let iconForeground: UIImageView + + private let title = ComponentView() + private let mainText = ComponentView() + + private var chevronImage: UIImage? + + private var items: [Item] = [] + + private var component: CollectibleItemInfoScreenContentComponent? + + public override init(frame: CGRect) { + self.scrollView = UIScrollView() + + self.iconBackground = UIImageView() + self.iconForeground = UIImageView() + + super.init(frame: frame) + + self.addSubview(self.scrollView) + + self.scrollView.delaysContentTouches = false + self.scrollView.contentInsetAdjustmentBehavior = .never + if #available(iOS 13.0, *) { + self.scrollView.automaticallyAdjustsScrollIndicatorInsets = false + } + self.scrollView.showsVerticalScrollIndicator = false + self.scrollView.showsHorizontalScrollIndicator = false + self.scrollView.alwaysBounceHorizontal = false + self.scrollView.scrollsToTop = false + self.scrollView.clipsToBounds = false + + self.scrollView.addSubview(self.iconBackground) + self.scrollView.addSubview(self.iconForeground) + } + + required init(coder: NSCoder) { + preconditionFailure() + } + + public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { + if let result = super.hitTest(point, with: event) { + return result + } else { + return nil + } + } + + func update(component: CollectibleItemInfoScreenContentComponent, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + self.component = component + + let sideInset: CGFloat = 16.0 + let sideIconInset: CGFloat = 40.0 + + var contentHeight: CGFloat = 0.0 + + let iconSize: CGFloat = 90.0 + if self.iconBackground.image == nil { + let backgroundColors = component.theme.chatList.pinnedArchiveAvatarColor.backgroundColors.colors + let colors: NSArray = [backgroundColors.1.cgColor, backgroundColors.0.cgColor] + self.iconBackground.image = generateGradientFilledCircleImage(diameter: iconSize, colors: colors) + } + let iconBackgroundFrame = CGRect(origin: CGPoint(x: floor((availableSize.width - iconSize) * 0.5), y: contentHeight), size: CGSize(width: iconSize, height: iconSize)) + transition.setFrame(view: self.iconBackground, frame: iconBackgroundFrame) + + if self.iconForeground.image == nil { + self.iconForeground.image = generateTintedImage(image: UIImage(bundleImageName: "Chat List/ArchiveIconLarge"), color: .white) + } + if let image = self.iconForeground.image { + transition.setFrame(view: self.iconForeground, frame: CGRect(origin: CGPoint(x: iconBackgroundFrame.minX + floor((iconBackgroundFrame.width - image.size.width) * 0.5), y: iconBackgroundFrame.minY + floor((iconBackgroundFrame.height - image.size.height) * 0.5)), size: image.size)) + } + + contentHeight += iconSize + contentHeight += 15.0 + + let titleString = NSMutableAttributedString() + titleString.append(NSAttributedString(string: component.strings.ArchiveInfo_Title, font: Font.semibold(19.0), textColor: component.theme.list.itemPrimaryTextColor)) + let imageAttachment = NSTextAttachment() + imageAttachment.image = self.iconBackground.image + titleString.append(NSAttributedString(attachment: imageAttachment)) + + let titleSize = self.title.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(titleString), + maximumNumberOfLines: 1 + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0) + ) + if let titleView = self.title.view { + if titleView.superview == nil { + self.scrollView.addSubview(titleView) + } + transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - titleSize.width) * 0.5), y: contentHeight), size: titleSize)) + } + contentHeight += titleSize.height + contentHeight += 16.0 + + let text: String + if component.settings.keepArchivedUnmuted { + text = component.strings.ArchiveInfo_TextKeepArchivedUnmuted + } else { + text = component.strings.ArchiveInfo_TextKeepArchivedDefault + } + + let mainText = NSMutableAttributedString() + mainText.append(parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes( + body: MarkdownAttributeSet( + font: Font.regular(15.0), + textColor: component.theme.list.itemSecondaryTextColor + ), + bold: MarkdownAttributeSet( + font: Font.semibold(15.0), + textColor: component.theme.list.itemSecondaryTextColor + ), + link: MarkdownAttributeSet( + font: Font.regular(15.0), + textColor: component.theme.list.itemAccentColor, + additionalAttributes: [:] + ), + linkAttribute: { attributes in + return ("URL", "") + } + ))) + if self.chevronImage == nil { + self.chevronImage = UIImage(bundleImageName: "Settings/TextArrowRight") + } + if let range = mainText.string.range(of: ">"), let chevronImage = self.chevronImage { + mainText.addAttribute(.attachment, value: chevronImage, range: NSRange(range, in: mainText.string)) + } + + let mainTextSize = self.mainText.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(mainText), + horizontalAlignment: .center, + maximumNumberOfLines: 0, + lineSpacing: 0.2, + highlightColor: component.theme.list.itemAccentColor.withMultipliedAlpha(0.1), + highlightAction: { attributes in + if let _ = attributes[NSAttributedString.Key(rawValue: "URL")] { + return NSAttributedString.Key(rawValue: "URL") + } else { + return nil + } + }, + tapAction: { [weak self] _, _ in + guard let self, let component = self.component else { + return + } + component.openSettings() + } + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0, height: 1000.0) + ) + if let mainTextView = self.mainText.view { + if mainTextView.superview == nil { + self.scrollView.addSubview(mainTextView) + } + transition.setFrame(view: mainTextView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - mainTextSize.width) * 0.5), y: contentHeight), size: mainTextSize)) + } + contentHeight += mainTextSize.height + + contentHeight += 24.0 + + struct ItemDesc { + var icon: String + var title: String + var text: String + } + let itemDescs: [ItemDesc] = [ + ItemDesc( + icon: "Chat List/Archive/IconArchived", + title: component.strings.ArchiveInfo_ChatsTitle, + text: component.strings.ArchiveInfo_ChatsText + ), + ItemDesc( + icon: "Chat List/Archive/IconHide", + title: component.strings.ArchiveInfo_HideTitle, + text: component.strings.ArchiveInfo_HideText + ), + ItemDesc( + icon: "Chat List/Archive/IconStories", + title: component.strings.ArchiveInfo_StoriesTitle, + text: component.strings.ArchiveInfo_StoriesText + ) + ] + for i in 0 ..< itemDescs.count { + if i != 0 { + contentHeight += 24.0 + } + + let item: Item + if self.items.count > i { + item = self.items[i] + } else { + item = Item() + self.items.append(item) + } + + let itemDesc = itemDescs[i] + + let iconSize = item.icon.update( + transition: .immediate, + component: AnyComponent(BundleIconComponent( + name: itemDesc.icon, + tintColor: component.theme.list.itemAccentColor + )), + environment: {}, + containerSize: CGSize(width: 100.0, height: 100.0) + ) + let titleSize = item.title.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: itemDesc.title, font: Font.semibold(15.0), textColor: component.theme.list.itemPrimaryTextColor)), + maximumNumberOfLines: 0, + lineSpacing: 0.2 + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0 - sideIconInset, height: 1000.0) + ) + let textSize = item.text.update( + transition: .immediate, + component: AnyComponent(MultilineTextComponent( + text: .plain(NSAttributedString(string: itemDesc.text, font: Font.regular(15.0), textColor: component.theme.list.itemSecondaryTextColor)), + maximumNumberOfLines: 0, + lineSpacing: 0.18 + )), + environment: {}, + containerSize: CGSize(width: availableSize.width - sideInset * 2.0 - sideIconInset, height: 1000.0) + ) + + if let iconView = item.icon.view { + if iconView.superview == nil { + self.scrollView.addSubview(iconView) + } + transition.setFrame(view: iconView, frame: CGRect(origin: CGPoint(x: sideInset, y: contentHeight + 4.0), size: iconSize)) + } + + if let titleView = item.title.view { + if titleView.superview == nil { + self.scrollView.addSubview(titleView) + } + transition.setFrame(view: titleView, frame: CGRect(origin: CGPoint(x: sideInset + sideIconInset, y: contentHeight), size: titleSize)) + } + contentHeight += titleSize.height + contentHeight += 2.0 + + if let textView = item.text.view { + if textView.superview == nil { + self.scrollView.addSubview(textView) + } + transition.setFrame(view: textView, frame: CGRect(origin: CGPoint(x: sideInset + sideIconInset, y: contentHeight), size: textSize)) + } + contentHeight += textSize.height + } + + let contentSize = CGSize(width: availableSize.width, height: contentHeight) + let size = CGSize(width: availableSize.width, height: min(availableSize.height, contentSize.height)) + if self.scrollView.bounds.size != size || self.scrollView.contentSize != contentSize { + self.scrollView.frame = CGRect(origin: CGPoint(), size: size) + self.scrollView.contentSize = contentSize + } + + 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) + } +} +*/ diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleTonSymbolInline.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleTonSymbolInline.imageset/Contents.json new file mode 100644 index 0000000000..4488755ba2 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleTonSymbolInline.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "ton_12.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleTonSymbolInline.imageset/ton_12.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleTonSymbolInline.imageset/ton_12.pdf new file mode 100644 index 0000000000..238337b6c9 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleTonSymbolInline.imageset/ton_12.pdf @@ -0,0 +1,83 @@ +%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.143555 0.130127 cm +0.000000 0.000000 0.000000 scn +5.156074 3.095078 m +1.539963 9.669825 l +5.156074 9.669825 l +5.156074 3.095078 l +h +6.556074 3.095079 m +10.172184 9.669825 l +6.556074 9.669825 l +6.556074 3.095079 l +h +1.201709 11.069824 m +0.288984 11.069824 -0.289608 10.091264 0.150250 9.291522 c +4.804615 0.829041 l +5.260527 0.000110 6.451622 0.000113 6.907533 0.829041 c +11.561897 9.291523 l +12.001758 10.091268 11.423159 11.069824 10.510438 11.069824 c +1.201709 11.069824 l +h +f* +n +Q + +endstream +endobj + +3 0 obj + 553 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 12.000000 12.000000 ] + /Resources 1 0 R + /Contents 2 0 R + /Parent 5 0 R + >> +endobj + +5 0 obj + << /Kids [ 4 0 R ] + /Count 1 + /Type /Pages + >> +endobj + +6 0 obj + << /Pages 5 0 R + /Type /Catalog + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000010 00000 n +0000000034 00000 n +0000000643 00000 n +0000000665 00000 n +0000000838 00000 n +0000000912 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +971 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleUsernameInfoTitleIcon.imageset/Contents.json b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleUsernameInfoTitleIcon.imageset/Contents.json new file mode 100644 index 0000000000..6a062695f3 --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleUsernameInfoTitleIcon.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "filename" : "username.pdf", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleUsernameInfoTitleIcon.imageset/username.pdf b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleUsernameInfoTitleIcon.imageset/username.pdf new file mode 100644 index 0000000000..548f72b27c --- /dev/null +++ b/submodules/TelegramUI/Images.xcassets/Peer Info/CollectibleUsernameInfoTitleIcon.imageset/username.pdf @@ -0,0 +1,100 @@ +%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 19.254883 19.005127 cm +0.000000 0.000000 0.000000 scn +0.000000 25.994989 m +0.000000 40.351631 11.638357 51.989990 25.995001 51.989990 c +40.351643 51.989990 51.989998 40.351631 51.989998 25.994989 c +51.989998 19.994989 l +51.989998 15.579475 48.410515 11.999992 43.994999 11.999992 c +40.680130 11.999992 37.836452 14.017384 36.624741 16.891380 c +34.058002 13.897156 30.248056 11.999989 25.995001 11.999989 c +18.265776 11.999989 12.000000 18.265766 12.000000 25.994989 c +12.000000 33.724213 18.265776 39.989990 25.995001 39.989990 c +29.919403 39.989990 33.466534 38.374702 36.007809 35.772713 c +36.097725 36.791267 36.953087 37.589989 37.994999 37.589989 c +39.096806 37.589989 39.989998 36.696800 39.989998 35.594986 c +39.989998 26.005434 l +39.990002 25.994989 l +39.989998 25.984545 l +39.989998 19.994995 l +39.989998 17.783092 41.783100 15.989990 43.994999 15.989990 c +46.206898 15.989990 48.000000 17.783092 48.000000 19.994989 c +48.000000 25.994989 l +48.000000 38.148018 38.148026 47.999989 25.995001 47.999989 c +13.841973 47.999989 3.990000 38.148018 3.990000 25.994989 c +3.990000 25.793646 3.992699 25.592970 3.998061 25.392994 c +4.317001 13.518284 14.043282 3.989990 25.995001 3.989990 c +29.449270 3.989990 32.712318 4.784481 35.616467 6.198845 c +36.607044 6.681271 37.801151 6.269333 38.283577 5.278755 c +38.766006 4.288174 38.354069 3.094070 37.363487 2.611641 c +33.926983 0.938011 30.067709 -0.000008 25.995001 -0.000008 c +11.638357 -0.000008 0.000000 11.638348 0.000000 25.994989 c +h +25.995001 35.999992 m +31.520609 35.999992 35.999996 31.520597 35.999996 25.994989 c +35.999996 20.469381 31.520609 15.989994 25.995001 15.989994 c +20.469393 15.989994 15.990000 20.469381 15.990000 25.994989 c +15.990000 31.520597 20.469393 35.999992 25.995001 35.999992 c +h +f* +n +Q + +endstream +endobj + +3 0 obj + 1836 +endobj + +4 0 obj + << /Annots [] + /Type /Page + /MediaBox [ 0.000000 0.000000 90.000000 90.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 +0000001926 00000 n +0000001949 00000 n +0000002122 00000 n +0000002196 00000 n +trailer +<< /ID [ (some) (id) ] + /Root 6 0 R + /Size 7 +>> +startxref +2255 +%%EOF \ No newline at end of file diff --git a/submodules/TelegramUI/Resources/Animations/ToastCollectibleUsernameEmoji.tgs b/submodules/TelegramUI/Resources/Animations/ToastCollectibleUsernameEmoji.tgs new file mode 100644 index 0000000000..f93fd6d746 Binary files /dev/null and b/submodules/TelegramUI/Resources/Animations/ToastCollectibleUsernameEmoji.tgs differ diff --git a/submodules/TelegramUI/Sources/SharedAccountContext.swift b/submodules/TelegramUI/Sources/SharedAccountContext.swift index f454f44991..37b233f7af 100644 --- a/submodules/TelegramUI/Sources/SharedAccountContext.swift +++ b/submodules/TelegramUI/Sources/SharedAccountContext.swift @@ -55,6 +55,7 @@ import ChatbotSetupScreen import BusinessLocationSetupScreen import BusinessHoursSetupScreen import AutomaticBusinessMessageSetupScreen +import CollectibleItemInfoScreen private final class AccountUserInterfaceInUseContext { let subscribers = Bag<(Bool) -> Void>() @@ -1923,6 +1924,14 @@ public final class SharedAccountContextImpl: SharedAccountContext { return QuickReplySetupScreen.initialData(context: context) } + public func makeCollectibleItemInfoScreen(context: AccountContext, initialData: CollectibleItemInfoScreenInitialData) -> ViewController { + return CollectibleItemInfoScreen(context: context, initialData: initialData as! CollectibleItemInfoScreen.InitialData) + } + + public func makeCollectibleItemInfoScreenInitialData(context: AccountContext, peerId: EnginePeer.Id, subject: CollectibleItemInfoScreenSubject) -> Signal { + return CollectibleItemInfoScreen.initialData(context: context, peerId: peerId, subject: subject) + } + public func makePremiumIntroController(context: AccountContext, source: PremiumIntroSource, forceDark: Bool, dismissed: (() -> Void)?) -> ViewController { var modal = true let mappedSource: PremiumSource