Merge commit '62ff5b04ece5a28032b7ae830970d7d77af7ca3d' into lottie-temp

This commit is contained in:
Isaac 2024-05-16 19:38:19 +04:00
commit f14b1161ea
92 changed files with 40819 additions and 39245 deletions

View File

@ -12190,3 +12190,19 @@ Sorry for the inconvenience.";
"EmojiPacks.UnarchiveEmojiPacksConfirmation_1" = "Unarchive %@ Pack";
"EmojiPacks.UnarchiveEmojiPacksConfirmation_any" = "Unarchive %@ Packs";
"HashtagSearch.ThisChat" = "This Chat";
"HashtagSearch.MyMessages" = "My Messages";
"HashtagSearch.PublicPosts" = "Public Posts";
"Chat.Context.Phone.AddToContacts" = "Add to Contacts";
"Chat.Context.Phone.CreateNewContact" = "Create New Contact";
"Chat.Context.Phone.AddToExistingContact" = "Add to Existing Contact";
"Chat.Context.Phone.SendMessage" = "Send Message";
"Chat.Context.Phone.TelegramVoiceCall" = "Telegram Voice Call";
"Chat.Context.Phone.TelegramVideoCall" = "Telegram Video Call";
"Chat.Context.Phone.InviteToTelegram" = "Invite to Telegram";
"Chat.Context.Phone.CallViaCarrier" = "Call via Carrier";
"Chat.Context.Phone.CopyNumber" = "Copy Number";
"Chat.Context.Phone.NotOnTelegram" = "This number is not on Telegram.";
"Chat.Context.Phone.ViewProfile" = "View Profile";

View File

@ -933,7 +933,7 @@ public protocol SharedAccountContext: AnyObject {
func makeOverlayAudioPlayerController(context: AccountContext, chatLocation: ChatLocation, type: MediaManagerPlayerType, initialMessageId: MessageId, initialOrder: MusicPlaybackSettingsOrder, playlistLocation: SharedMediaPlaylistLocation?, parentNavigationController: NavigationController?) -> ViewController & OverlayAudioPlayerController
func makePeerInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, peer: Peer, mode: PeerInfoControllerMode, avatarInitiallyExpanded: Bool, fromChat: Bool, requestsContext: PeerInvitationImportersContext?) -> ViewController?
func makeChannelAdminController(context: AccountContext, peerId: PeerId, adminId: PeerId, initialParticipant: ChannelParticipant) -> ViewController?
func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController
func makeDeviceContactInfoController(context: ShareControllerAccountContext, environment: ShareControllerEnvironment, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController
func makePeersNearbyController(context: AccountContext) -> ViewController
func makeComposeController(context: AccountContext) -> ViewController
func makeChatListController(context: AccountContext, location: ChatListControllerLocation, controlsHistoryPreload: Bool, hideNetworkActivityStatus: Bool, previewing: Bool, enableDebugActions: Bool) -> ChatListController
@ -1248,3 +1248,28 @@ public struct StickersSearchConfiguration {
}
}
}
public protocol ShareControllerAccountContext: AnyObject {
var accountId: AccountRecordId { get }
var accountPeerId: EnginePeer.Id { get }
var stateManager: AccountStateManager { get }
var engineData: TelegramEngine.EngineData { get }
var animationCache: AnimationCache { get }
var animationRenderer: MultiAnimationRenderer { get }
var contentSettings: ContentSettings { get }
var appConfiguration: AppConfiguration { get }
func resolveInlineStickers(fileIds: [Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>
}
public protocol ShareControllerEnvironment: AnyObject {
var presentationData: PresentationData { get }
var updatedPresentationData: Signal<PresentationData, NoError> { get }
var isMainApp: Bool { get }
var energyUsageSettings: EnergyUsageSettings { get }
var mediaManager: MediaManager? { get }
func setAccountUserInterfaceInUse(id: AccountRecordId) -> Disposable
func donateSendMessageIntent(account: ShareControllerAccountContext, peerIds: [EnginePeer.Id])
}

View File

@ -971,6 +971,7 @@ public protocol ChatController: ViewController {
var chatLocation: ChatLocation { get }
var canReadHistory: ValuePromise<Bool> { get }
var parentController: ViewController? { get set }
var customNavigationController: NavigationController? { get set }
var purposefulAction: (() -> Void)? { get set }

View File

@ -28,13 +28,22 @@ public final class BotCheckoutController: ViewController {
}
public static func fetch(context: AccountContext, source: BotPaymentInvoiceSource) -> Signal<InputData, FetchError> {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let theme = context.sharedContext.currentPresentationData.with { $0 }.theme
let themeParams: [String: Any] = [
"bg_color": Int32(bitPattern: presentationData.theme.list.plainBackgroundColor.argb),
"text_color": Int32(bitPattern: presentationData.theme.list.itemPrimaryTextColor.argb),
"link_color": Int32(bitPattern: presentationData.theme.list.itemAccentColor.argb),
"button_color": Int32(bitPattern: presentationData.theme.list.itemCheckColors.fillColor.argb),
"button_text_color": Int32(bitPattern: presentationData.theme.list.itemCheckColors.foregroundColor.argb)
"bg_color": Int32(bitPattern: theme.list.plainBackgroundColor.rgb),
"secondary_bg_color": Int32(bitPattern: theme.list.blocksBackgroundColor.rgb),
"text_color": Int32(bitPattern: theme.list.itemPrimaryTextColor.rgb),
"hint_color": Int32(bitPattern: theme.list.itemSecondaryTextColor.rgb),
"link_color": Int32(bitPattern: theme.list.itemAccentColor.rgb),
"button_color": Int32(bitPattern: theme.list.itemCheckColors.fillColor.rgb),
"button_text_color": Int32(bitPattern: theme.list.itemCheckColors.foregroundColor.rgb),
"header_bg_color": Int32(bitPattern: theme.rootController.navigationBar.opaqueBackgroundColor.rgb),
"accent_text_color": Int32(bitPattern: theme.list.itemAccentColor.rgb),
"section_bg_color": Int32(bitPattern: theme.list.itemBlocksBackgroundColor.rgb),
"section_header_text_color": Int32(bitPattern: theme.list.freeTextColor.rgb),
"subtitle_text_color": Int32(bitPattern: theme.list.itemSecondaryTextColor.rgb),
"destructive_text_color": Int32(bitPattern: theme.list.itemDestructiveColor.rgb),
"section_separator_color": Int32(bitPattern: theme.list.itemBlocksSeparatorColor.rgb)
]
return context.engine.payments.fetchBotPaymentForm(source: source, themeParams: themeParams)

View File

@ -23,6 +23,7 @@ import StoryContainerScreen
import ChatListHeaderComponent
import TelegramIntents
import UndoUI
import ShareController
private final class HeaderContextReferenceContentSource: ContextReferenceContentSource {
private let controller: ViewController
@ -309,7 +310,7 @@ public class ContactsController: ViewController {
guard let strongSelf = self, let value = value else {
return
}
(strongSelf.navigationController as? NavigationController)?.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .vcard(nil, id, value), completed: nil, cancelled: nil), completion: { [weak self] in
(strongSelf.navigationController as? NavigationController)?.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .vcard(nil, id, value), completed: nil, cancelled: nil), completion: { [weak self] in
if let strongSelf = self {
strongSelf.contactsNode.contactListNode.listNode.clearHighlightAnimated(true)
}
@ -741,7 +742,7 @@ public class ContactsController: ViewController {
case .allowed:
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: "", lastName: "", phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!<Mobile>!$_", value: "+")]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
if let navigationController = strongSelf.context.sharedContext.mainWindow?.viewController as? NavigationController {
navigationController.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
navigationController.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
guard let strongSelf = self else {
return
}
@ -755,7 +756,7 @@ public class ContactsController: ViewController {
}
} else {
if let navigationController = strongSelf.context.sharedContext.mainWindow?.viewController as? NavigationController {
navigationController.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil))
navigationController.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil))
}
}
}), completed: nil, cancelled: nil))

View File

@ -121,6 +121,19 @@ public final class ContextActionNode: ASDisplayNode, ContextActionNodeProtocol {
statusNode.attributedText = NSAttributedString(string: value, font: subtitleFont, textColor: presentationData.theme.contextMenu.secondaryColor)
statusNode.maximumNumberOfLines = 1
self.statusNode = statusNode
case let .secondLineWithAttributedValue(value):
self.textNode.maximumNumberOfLines = 1
let statusNode = ImmediateTextNode()
statusNode.isAccessibilityElement = false
statusNode.isUserInteractionEnabled = false
statusNode.displaysAsynchronously = false
let mutableString = value.mutableCopy() as! NSMutableAttributedString
mutableString.addAttribute(.foregroundColor, value: presentationData.theme.contextMenu.secondaryColor, range: NSRange(location: 0, length: mutableString.length))
mutableString.addAttribute(.font, value: subtitleFont, range: NSRange(location: 0, length: mutableString.length))
statusNode.attributedText = mutableString
statusNode.maximumNumberOfLines = 1
self.statusNode = statusNode
case .multiline:
self.textNode.maximumNumberOfLines = 0
self.statusNode = nil
@ -350,10 +363,15 @@ public final class ContextActionNode: ASDisplayNode, ContextActionNodeProtocol {
self.textNode.attributedText = NSAttributedString(string: self.action.text, font: titleFont, textColor: textColor)
let subtitleFont = Font.regular(presentationData.listsFontSize.baseDisplaySize * 13.0 / 17.0)
switch self.action.textLayout {
case let .secondLineWithValue(value):
let subtitleFont = Font.regular(presentationData.listsFontSize.baseDisplaySize * 13.0 / 17.0)
self.statusNode?.attributedText = NSAttributedString(string: value, font: subtitleFont, textColor: presentationData.theme.contextMenu.secondaryColor)
case let .secondLineWithAttributedValue(value):
let mutableString = value.mutableCopy() as! NSMutableAttributedString
mutableString.addAttribute(.foregroundColor, value: presentationData.theme.contextMenu.secondaryColor, range: NSRange(location: 0, length: mutableString.length))
mutableString.addAttribute(.font, value: subtitleFont, range: NSRange(location: 0, length: mutableString.length))
self.statusNode?.attributedText = mutableString
default:
break
}

View File

@ -36,6 +36,7 @@ public enum ContextMenuActionItemTextLayout {
case singleLine
case twoLinesMax
case secondLineWithValue(String)
case secondLineWithAttributedValue(NSAttributedString)
case multiline
}
@ -2150,6 +2151,7 @@ public protocol ContextExtractedContentSource: AnyObject {
var initialAppearanceOffset: CGPoint { get }
var centerVertically: Bool { get }
var keepInPlace: Bool { get }
var adjustContentHorizontally: Bool { get }
var adjustContentForSideInset: Bool { get }
var ignoreContentTouches: Bool { get }
var blurBackground: Bool { get }
@ -2170,6 +2172,10 @@ public extension ContextExtractedContentSource {
return false
}
var adjustContentHorizontally: Bool {
return false
}
var adjustContentForSideInset: Bool {
return false
}

View File

@ -228,21 +228,7 @@ public final class ContextControllerActionsListActionItemNode: HighlightTracking
let iconSpacing: CGFloat = 8.0
self.highlightBackgroundNode.backgroundColor = presentationData.theme.contextMenu.itemHighlightedBackgroundColor
var subtitle: String?
switch self.item.textLayout {
case .singleLine:
self.titleLabelNode.maximumNumberOfLines = 1
case .twoLinesMax:
self.titleLabelNode.maximumNumberOfLines = 2
case let .secondLineWithValue(subtitleValue):
self.titleLabelNode.maximumNumberOfLines = 1
subtitle = subtitleValue
case .multiline:
self.titleLabelNode.maximumNumberOfLines = 0
self.titleLabelNode.lineSpacing = 0.1
}
var forcedHeight: CGFloat?
var titleVerticalOffset: CGFloat?
let titleFont: UIFont
@ -265,6 +251,30 @@ public final class ContextControllerActionsListActionItemNode: HighlightTracking
let subtitleFont = Font.regular(presentationData.listsFontSize.baseDisplaySize * 14.0 / 17.0)
let subtitleColor = presentationData.theme.contextMenu.secondaryColor
var subtitle: NSAttributedString?
switch self.item.textLayout {
case .singleLine:
self.titleLabelNode.maximumNumberOfLines = 1
case .twoLinesMax:
self.titleLabelNode.maximumNumberOfLines = 2
case let .secondLineWithValue(subtitleValue):
self.titleLabelNode.maximumNumberOfLines = 1
subtitle = NSAttributedString(
string: subtitleValue,
font: subtitleFont,
textColor: subtitleColor
)
case let .secondLineWithAttributedValue(subtitleValue):
self.titleLabelNode.maximumNumberOfLines = 1
let mutableString = subtitleValue.mutableCopy() as! NSMutableAttributedString
mutableString.addAttribute(.foregroundColor, value: subtitleColor, range: NSRange(location: 0, length: mutableString.length))
mutableString.addAttribute(.font, value: subtitleFont, range: NSRange(location: 0, length: mutableString.length))
subtitle = mutableString
case .multiline:
self.titleLabelNode.maximumNumberOfLines = 0
self.titleLabelNode.lineSpacing = 0.1
}
let titleColor: UIColor
switch self.item.textColor {
case .primary:
@ -308,13 +318,7 @@ public final class ContextControllerActionsListActionItemNode: HighlightTracking
self.titleLabelNode.isUserInteractionEnabled = self.titleLabelNode.tapAttributeAction != nil && self.item.action == nil
self.subtitleNode.attributedText = subtitle.flatMap { subtitle in
return NSAttributedString(
string: subtitle,
font: subtitleFont,
textColor: subtitleColor
)
}
self.subtitleNode.attributedText = subtitle
var iconSize: CGSize?
if let iconSource = self.item.iconSource {

View File

@ -1064,6 +1064,9 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
if let contentNode = itemContentNode {
var contentFrame = CGRect(origin: CGPoint(x: contentParentGlobalFrame.minX + contentRect.minX - contentNode.containingItem.contentRect.minX, y: contentRect.minY - contentNode.containingItem.contentRect.minY + contentVerticalOffset + additionalVisibleOffsetY), size: contentNode.containingItem.view.bounds.size)
if case let .extracted(extracted) = self.source {
if extracted.adjustContentHorizontally {
contentFrame.origin.x = combinedActionsFrame.minX
}
if extracted.centerVertically {
if combinedActionsFrame.height.isZero {
contentFrame.origin.y = floorToScreenPixels((layout.size.height - contentFrame.height) / 2.0)
@ -1160,7 +1163,10 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
let contentX = contentParentGlobalFrame.minX + contentRect.minX - contentNode.containingItem.contentRect.minX
let contentWidth = contentNode.containingItem.view.bounds.size.width
let contentHeight = contentNode.containingItem.view.bounds.size.height
if case let .extracted(extracted) = self.source, extracted.centerVertically {
if case let .extracted(extracted) = self.source, extracted.adjustContentHorizontally {
let fixedContentX = self.actionsContainerNode.frame.minX
animationInContentXDistance = fixedContentX - contentX
} else if case let .extracted(extracted) = self.source, extracted.centerVertically {
if actionsSize.height.isZero {
var initialContentRect = contentRect
initialContentRect.origin.y += extracted.initialAppearanceOffset.y
@ -1429,7 +1435,10 @@ final class ContextControllerExtractedPresentationNode: ASDisplayNode, ContextCo
var animationInContentXDistance: CGFloat = 0.0
let contentX = contentParentGlobalFrame.minX + contentRect.minX - contentNode.containingItem.contentRect.minX
let contentWidth = contentNode.containingItem.view.bounds.size.width
if case let .extracted(extracted) = self.source, extracted.centerVertically {
if case let .extracted(extracted) = self.source, extracted.adjustContentHorizontally {
let fixedContentX = self.actionsContainerNode.frame.minX
animationInContentXDistance = contentX - fixedContentX
} else if case let .extracted(extracted) = self.source, extracted.centerVertically {
if actionsSize.height.isZero {
// let fixedContentY = floorToScreenPixels((layout.size.height - contentHeight) / 2.0)
animationInContentYDistance = 0.0 //contentY - fixedContentY

View File

@ -330,7 +330,7 @@ public func generateTintedImage(image: UIImage?, color: UIColor, backgroundColor
return tintedImage
}
public func generateGradientTintedImage(image: UIImage?, colors: [UIColor]) -> UIImage? {
public func generateGradientTintedImage(image: UIImage?, colors: [UIColor], direction: GradientImageDirection = .vertical) -> UIImage? {
guard let image = image else {
return nil
}
@ -357,7 +357,21 @@ public func generateGradientTintedImage(image: UIImage?, colors: [UIColor]) -> U
let colorSpace = DeviceGraphicsContextSettings.shared.colorSpace
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: imageRect.height), end: CGPoint(x: 0.0, y: 0.0), options: CGGradientDrawingOptions())
let start: CGPoint
let end: CGPoint
switch direction {
case .horizontal:
start = .zero
end = CGPoint(x: imageRect.width, y: 0.0)
case .vertical:
start = CGPoint(x: 0.0, y: imageRect.height)
end = .zero
case .diagonal:
start = CGPoint(x: 0.0, y: 0.0)
end = CGPoint(x: imageRect.width, y: imageRect.height)
}
context.drawLinearGradient(gradient, start: start, end: end, options: CGGradientDrawingOptions())
} else if !colors.isEmpty {
context.setFillColor(colors[0].cgColor)
context.fill(imageRect)

View File

@ -1327,8 +1327,6 @@ private extension UIBezierPath {
}
}
extension UIImageView {
func setDrawingAnimatedImage(data: Data) {
DispatchQueue.global().async {
@ -1354,48 +1352,3 @@ extension UIImageView {
self.animationRepeatCount = 0
}
}
//private func prerenderEntityTransformations(entity: DrawingEntity, image: UIImage, colorSpace: CGColorSpace) -> UIImage {
// let imageSize = image.size
//
// let angle: CGFloat
// var scale: CGFloat
// let position: CGPoint
//
// if let entity = entity as? DrawingStickerEntity {
// angle = -entity.rotation
// scale = entity.scale
// position = entity.position
// } else {
// fatalError()
// }
//
// let rotatedSize = CGSize(
// width: abs(imageSize.width * cos(angle)) + abs(imageSize.height * sin(angle)),
// height: abs(imageSize.width * sin(angle)) + abs(imageSize.height * cos(angle))
// )
// let newSize = CGSize(width: rotatedSize.width * scale, height: rotatedSize.height * scale)
//
// let newImage = generateImage(newSize, contextGenerator: { size, context in
// context.setAllowsAntialiasing(true)
// context.setShouldAntialias(true)
// context.interpolationQuality = .high
// context.clear(CGRect(origin: .zero, size: size))
// context.translateBy(x: newSize.width * 0.5, y: newSize.height * 0.5)
// context.rotate(by: angle)
// context.scaleBy(x: scale, y: scale)
// let drawRect = CGRect(
// x: -imageSize.width * 0.5,
// y: -imageSize.height * 0.5,
// width: imageSize.width,
// height: imageSize.height
// )
// if let cgImage = image.cgImage {
// context.draw(cgImage, in: drawRect)
// }
// }, scale: 1.0)!
//
// let _ = position
//
// return newImage
//}

View File

@ -582,6 +582,7 @@ private final class PendingInAppPurchaseState: Codable {
case prizeDescription
case randomId
case untilDate
case stars
}
enum PurposeType: Int32 {
@ -591,6 +592,7 @@ private final class PendingInAppPurchaseState: Codable {
case gift
case giftCode
case giveaway
case stars
}
case subscription
@ -599,6 +601,7 @@ private final class PendingInAppPurchaseState: Codable {
case gift(peerId: EnginePeer.Id)
case giftCode(peerIds: [EnginePeer.Id], boostPeer: EnginePeer.Id?)
case giveaway(boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32)
case stars(count: Int64)
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
@ -631,6 +634,8 @@ private final class PendingInAppPurchaseState: Codable {
randomId: try container.decode(Int64.self, forKey: .randomId),
untilDate: try container.decode(Int32.self, forKey: .untilDate)
)
case .stars:
self = .stars(count: try container.decode(Int64.self, forKey: .stars))
default:
throw DecodingError.generic
}
@ -663,6 +668,9 @@ private final class PendingInAppPurchaseState: Codable {
try container.encodeIfPresent(prizeDescription, forKey: .prizeDescription)
try container.encode(randomId, forKey: .randomId)
try container.encode(untilDate, forKey: .untilDate)
case let .stars(count):
try container.encode(PurposeType.stars.rawValue, forKey: .type)
try container.encode(count, forKey: .stars)
}
}
@ -680,6 +688,8 @@ private final class PendingInAppPurchaseState: Codable {
self = .giftCode(peerIds: peerIds, boostPeer: boostPeer)
case let .giveaway(boostPeer, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate, _, _):
self = .giveaway(boostPeer: boostPeer, additionalPeerIds: additionalPeerIds, countries: countries, onlyNewSubscribers: onlyNewSubscribers, showWinners: showWinners, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate)
case let .stars(count, _, _):
self = .stars(count: count)
}
}
@ -698,6 +708,8 @@ private final class PendingInAppPurchaseState: Codable {
return .giftCode(peerIds: peerIds, boostPeer: boostPeer, currency: currency, amount: amount)
case let .giveaway(boostPeer, additionalPeerIds, countries, onlyNewSubscribers, showWinners, prizeDescription, randomId, untilDate):
return .giveaway(boostPeer: boostPeer, additionalPeerIds: additionalPeerIds, countries: countries, onlyNewSubscribers: onlyNewSubscribers, showWinners: showWinners, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, currency: currency, amount: amount)
case let .stars(count):
return .stars(count: count, currency: currency, amount: amount)
}
}
}

View File

@ -1995,7 +1995,7 @@ private final class TwoFactorDataInputScreenNode: ViewControllerTracingNode, ASS
let changeEmailActionButtonFrame: CGRect
let resendCodeActionFrame: CGRect
let resendCodeActionButtonFrame: CGRect
if changeEmailActionSize.width + resendCodeActionSize.width > layout.size.width - buttonFrame.minX * 2.0 {
if changeEmailActionSize.width + resendCodeActionSize.width > layout.size.width - buttonFrame.minX * 2.0 - 32.0 {
changeEmailActionButtonFrame = CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.minY), size: CGSize(width: buttonFrame.width, height: buttonFrame.height))
changeEmailActionFrame = CGRect(origin: CGPoint(x: changeEmailActionButtonFrame.minX + floor((changeEmailActionButtonFrame.width - changeEmailActionSize.width) / 2.0), y: changeEmailActionButtonFrame.minY + floor((changeEmailActionButtonFrame.height - changeEmailActionSize.height) / 2.0)), size: changeEmailActionSize)
resendCodeActionButtonFrame = CGRect(origin: CGPoint(x: buttonFrame.minX, y: buttonFrame.maxY), size: CGSize(width: buttonFrame.width, height: buttonFrame.height))

View File

@ -24,6 +24,8 @@ import UndoUI
import GalleryUI
import PeerAvatarGalleryUI
import Postbox
import ShareController
import ContextUI
private enum DeviceContactInfoAction {
case sendMessage
@ -33,7 +35,7 @@ private enum DeviceContactInfoAction {
}
private final class DeviceContactInfoControllerArguments {
let context: AccountContext
let accountContext: AccountContext?
let isPlain: Bool
let updateEditingName: (ItemListAvatarAndNameInfoItemName) -> Void
let updatePhone: (Int64, String) -> Void
@ -50,8 +52,8 @@ private final class DeviceContactInfoControllerArguments {
let updateShareViaException: (Bool) -> Void
let openAvatar: (EnginePeer) -> Void
init(context: AccountContext, isPlain: Bool, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updatePhone: @escaping (Int64, String) -> Void, updatePhoneLabel: @escaping (Int64, String) -> Void, deletePhone: @escaping (Int64) -> Void, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, addPhoneNumber: @escaping () -> Void, performAction: @escaping (DeviceContactInfoAction) -> Void, toggleSelection: @escaping (DeviceContactInfoDataId) -> Void, callPhone: @escaping (String) -> Void, openUrl: @escaping (String) -> Void, openAddress: @escaping (DeviceContactAddressData) -> Void, displayCopyContextMenu: @escaping (DeviceContactInfoEntryTag, String) -> Void, updateShareViaException: @escaping (Bool) -> Void, openAvatar: @escaping (EnginePeer) -> Void) {
self.context = context
init(accountContext: AccountContext?, isPlain: Bool, updateEditingName: @escaping (ItemListAvatarAndNameInfoItemName) -> Void, updatePhone: @escaping (Int64, String) -> Void, updatePhoneLabel: @escaping (Int64, String) -> Void, deletePhone: @escaping (Int64) -> Void, setPhoneIdWithRevealedOptions: @escaping (Int64?, Int64?) -> Void, addPhoneNumber: @escaping () -> Void, performAction: @escaping (DeviceContactInfoAction) -> Void, toggleSelection: @escaping (DeviceContactInfoDataId) -> Void, callPhone: @escaping (String) -> Void, openUrl: @escaping (String) -> Void, openAddress: @escaping (DeviceContactAddressData) -> Void, displayCopyContextMenu: @escaping (DeviceContactInfoEntryTag, String) -> Void, updateShareViaException: @escaping (Bool) -> Void, openAvatar: @escaping (EnginePeer) -> Void) {
self.accountContext = accountContext
self.isPlain = isPlain
self.updateEditingName = updateEditingName
self.updatePhone = updatePhone
@ -404,7 +406,10 @@ private enum DeviceContactInfoEntry: ItemListNodeEntry {
let arguments = arguments as! DeviceContactInfoControllerArguments
switch self {
case let .info(_, _, _, dateTimeFormat, peer, state, jobSummary, _, hiddenAvatar):
return ItemListAvatarAndNameInfoItem(accountContext: arguments.context, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .contact, peer: peer, presence: nil, label: jobSummary, memberCount: nil, state: state, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks(withTopInset: false, withExtendedBottomInset: true), editingNameUpdated: { editingName in
guard let accountContext = arguments.accountContext else {
fatalError()
}
return ItemListAvatarAndNameInfoItem(accountContext: accountContext, presentationData: presentationData, dateTimeFormat: dateTimeFormat, mode: .contact, peer: peer, presence: nil, label: jobSummary, memberCount: nil, state: state, sectionId: self.section, style: arguments.isPlain ? .plain : .blocks(withTopInset: false, withExtendedBottomInset: true), editingNameUpdated: { editingName in
arguments.updateEditingName(editingName)
}, avatarTapped: {
if peer.smallProfileImage != nil {
@ -625,7 +630,7 @@ private func filteredContactData(contactData: DeviceContactExtendedData, exclude
return DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: contactData.basicData.firstName, lastName: contactData.basicData.lastName, phoneNumbers: phoneNumbers), middleName: contactData.middleName, prefix: contactData.prefix, suffix: contactData.suffix, organization: includeJob ? contactData.organization : "", jobTitle: includeJob ? contactData.jobTitle : "", department: includeJob ? contactData.department : "", emailAddresses: emailAddresses, urls: urls, addresses: addresses, birthdayDate: includeBirthday ? contactData.birthdayDate : nil, socialProfiles: socialProfiles, instantMessagingProfiles: instantMessagingProfiles, note: includeNote ? contactData.note : "")
}
private func deviceContactInfoEntries(account: Account, engine: TelegramEngine, presentationData: PresentationData, peer: EnginePeer?, isShare: Bool, shareViaException: Bool, contactData: DeviceContactExtendedData, isContact: Bool, state: DeviceContactInfoState, selecting: Bool, editingPhoneNumbers: Bool, hiddenAvatar: TelegramMediaImageRepresentation?) -> [DeviceContactInfoEntry] {
private func deviceContactInfoEntries(context: ShareControllerAccountContext, presentationData: PresentationData, peer: EnginePeer?, isShare: Bool, shareViaException: Bool, contactData: DeviceContactExtendedData, isContact: Bool, state: DeviceContactInfoState, selecting: Bool, editingPhoneNumbers: Bool, hiddenAvatar: TelegramMediaImageRepresentation?) -> [DeviceContactInfoEntry] {
var entries: [DeviceContactInfoEntry] = []
var editingName: ItemListAvatarAndNameInfoItemName?
@ -738,16 +743,20 @@ private func deviceContactInfoEntries(account: Account, engine: TelegramEngine,
var addressIndex = 0
for address in contactData.addresses {
let signal = geocodeLocation(address: address.asPostalAddress)
|> mapToSignal { coordinates -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in
if let (latitude, longitude) = coordinates {
let resource = MapSnapshotMediaResource(latitude: latitude, longitude: longitude, width: 90, height: 90)
return chatMapSnapshotImage(engine: engine, resource: resource)
} else {
return .single({ _ in return nil })
let signal: Signal<(TransformImageArguments) -> DrawingContext?, NoError>
if let context = context as? ShareControllerAppAccountContext {
signal = geocodeLocation(address: address.asPostalAddress)
|> mapToSignal { coordinates -> Signal<(TransformImageArguments) -> DrawingContext?, NoError> in
if let (latitude, longitude) = coordinates {
let resource = MapSnapshotMediaResource(latitude: latitude, longitude: longitude, width: 90, height: 90)
return chatMapSnapshotImage(engine: context.context.engine, resource: resource)
} else {
return .single({ _ in return nil })
}
}
} else {
signal = .single({ _ in return nil })
}
entries.append(.address(entries.count, addressIndex, presentationData.theme, localizedGenericContactFieldLabel(label: address.label, strings: presentationData.strings), address, signal, selecting ? !state.excludedComponents.contains(.address(address)) : nil))
addressIndex += 1
}
@ -828,7 +837,7 @@ private final class DeviceContactInfoController: ItemListController, MFMessageCo
}
}
public func deviceContactInfoController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController {
public func deviceContactInfoController(context: ShareControllerAccountContext, environment: ShareControllerEnvironment, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)? = nil, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController {
var initialState = DeviceContactInfoState()
if case let .create(peer, contactData, _, _, _) = subject {
var peerPhoneNumber: String?
@ -876,7 +885,11 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
var displayCopyContextMenuImpl: ((DeviceContactInfoEntryTag, String) -> Void)?
let presentationData = environment.presentationData
let callImpl: (String) -> Void = { number in
guard let context = (context as? ShareControllerAppAccountContext)?.context else {
return
}
let user: Signal<TelegramUser?, NoError>
if let peer = subject.peer {
user = context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peer.id))
@ -890,10 +903,10 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
} else {
user = .single(nil)
}
let _ = (user
|> deliverOnMainQueue).start(next: { user in
if let user = user, let phone = user.phone, formatPhoneNumber(phone) == formatPhoneNumber(number) {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
@ -932,7 +945,13 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
shareViaException = shareViaExceptionValue
}
let arguments = DeviceContactInfoControllerArguments(context: context, isPlain: !isShare, updateEditingName: { editingName in
let accountContext: AccountContext?
if let context = context as? ShareControllerAppAccountContext {
accountContext = context.context
} else {
accountContext = nil
}
let arguments = DeviceContactInfoControllerArguments(accountContext: accountContext, isPlain: !isShare, updateEditingName: { editingName in
updateState { state in
var state = state
if let _ = state.editingState {
@ -952,6 +971,9 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
return state
}
}, updatePhoneLabel: { id, currentLabel in
guard let context = (context as? ShareControllerAppAccountContext)?.context else {
return
}
pushControllerImpl?(phoneLabelController(context: context, currentLabel: currentLabel, completion: { value in
updateState { state in
var state = state
@ -1000,7 +1022,6 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
if subject.contactData.basicData.phoneNumbers.count == 1 {
inviteAction(subject.contactData.basicData.phoneNumbers[0].value)
} else {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let controller = ActionSheetController(presentationData: presentationData)
let dismissAction: () -> Void = { [weak controller] in
controller?.dismissAnimated()
@ -1020,7 +1041,7 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
presentControllerImpl?(controller, ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
}
case .createContact:
pushControllerImpl?(deviceContactInfoController(context: context, subject: .create(peer: subject.peer, contactData: subject.contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
pushControllerImpl?(deviceContactInfoController(context: context, environment: environment, subject: .create(peer: subject.peer, contactData: subject.contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
dismissImpl?(false)
}), completed: nil, cancelled: nil))
case .addToExisting:
@ -1059,9 +1080,9 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
})
let hiddenAvatarPromise = Promise<TelegramMediaImageRepresentation?>(nil)
let presentationData = updatedPresentationData?.signal ?? context.sharedContext.presentationData
let updatedPresentationData = updatedPresentationData?.signal ?? environment.updatedPresentationData
let previousEditingPhoneIds = Atomic<Set<Int64>?>(value: nil)
let signal = combineLatest(presentationData, statePromise.get(), contactData, hiddenAvatarPromise.get())
let signal = combineLatest(updatedPresentationData, statePromise.get(), contactData, hiddenAvatarPromise.get())
|> map { presentationData, state, peerAndContactData, hiddenAvatar -> (ItemListControllerState, (ItemListNodeState, Any)) in
var presentationData = presentationData
let updatedTheme = presentationData.theme.withModalBlocksBackground()
@ -1116,6 +1137,9 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
rightNavigationButton = ItemListNavigationButton(content: .text(isShare ? presentationData.strings.Common_Done : presentationData.strings.Compose_Create), style: .bold, enabled: (isShare || !filteredPhoneNumbers.isEmpty) && composedContactData != nil, action: {
if let composedContactData = composedContactData {
guard let context = (context as? ShareControllerAppAccountContext)?.context else {
return
}
var addToPrivacyExceptions = false
updateState { state in
var state = state
@ -1129,7 +1153,7 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
if share, filteredPhoneNumbers.count <= 1, let peer = peer {
addContactDisposable.set((context.engine.contacts.addContactInteractively(peerId: peer.id, firstName: composedContactData.basicData.firstName, lastName: composedContactData.basicData.lastName, phoneNumber: filteredPhoneNumbers.first?.value ?? "", addToPrivacyExceptions: shareViaException && addToPrivacyExceptions)
|> deliverOnMainQueue).start(error: { _ in
presentControllerImpl?(textAlertController(context: context, updatedPresentationData: updatedPresentationData, title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
presentControllerImpl?(textAlertController(context: context, updatedPresentationData: (environment.presentationData, updatedPresentationData), title: nil, text: presentationData.strings.Login_UnknownError, actions: [TextAlertAction(type: .defaultAction, title: presentationData.strings.Common_OK, action: {})]), nil)
}, completed: {
let _ = (contactDataManager.createContactWithData(composedContactData)
|> deliverOnMainQueue).start(next: { contactIdAndData in
@ -1250,7 +1274,7 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
focusItemTag = DeviceContactInfoEntryTag.editingPhone(insertedPhoneId)
}
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: deviceContactInfoEntries(account: context.account, engine: context.engine, presentationData: presentationData, peer: peerAndContactData.0, isShare: isShare, shareViaException: shareViaException, contactData: peerAndContactData.2, isContact: peerAndContactData.1 != nil, state: state, selecting: selecting, editingPhoneNumbers: editingPhones, hiddenAvatar: hiddenAvatar), style: isShare ? .blocks : .plain, focusItemTag: focusItemTag)
let listState = ItemListNodeState(presentationData: ItemListPresentationData(presentationData), entries: deviceContactInfoEntries(context: context, presentationData: presentationData, peer: peerAndContactData.0, isShare: isShare, shareViaException: shareViaException, contactData: peerAndContactData.2, isContact: peerAndContactData.1 != nil, state: state, selecting: selecting, editingPhoneNumbers: editingPhones, hiddenAvatar: hiddenAvatar), style: isShare ? .blocks : .plain, focusItemTag: focusItemTag)
return (controllerState, (listState, arguments))
}
@ -1258,24 +1282,27 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
actionsDisposable.dispose()
}
let controller = DeviceContactInfoController(context: context, state: signal)
let controller = DeviceContactInfoController(presentationData: ItemListPresentationData(environment.presentationData), updatedPresentationData: environment.updatedPresentationData |> map { ItemListPresentationData($0) }, state: signal, tabBarItem: nil)
controller.navigationPresentation = .modal
addToExistingImpl = { [weak controller] in
guard let controller = controller else {
guard let controller, let accountContext = (context as? ShareControllerAppAccountContext)?.context else {
return
}
addContactToExisting(context: context, parentController: controller, contactData: subject.contactData, completion: { peer, contactId, contactData in
replaceControllerImpl?(deviceContactInfoController(context: context, subject: .vcard(peer?._asPeer(), contactId, contactData), completed: nil, cancelled: nil))
addContactToExisting(context: accountContext, parentController: controller, contactData: subject.contactData, completion: { peer, contactId, contactData in
replaceControllerImpl?(deviceContactInfoController(context: context, environment: environment, subject: .vcard(peer?._asPeer(), contactId, contactData), completed: nil, cancelled: nil))
})
}
openChatImpl = { [weak controller] peerId in
guard let controller, let context = (context as? ShareControllerAppAccountContext)?.context else {
return
}
let _ = (context.engine.data.get(TelegramEngine.EngineData.Item.Peer.Peer(id: peerId))
|> deliverOnMainQueue).start(next: { peer in
guard let peer = peer else {
|> deliverOnMainQueue).start(next: { [weak controller] peer in
guard let peer, let controller else {
return
}
if let navigationController = (controller?.navigationController as? NavigationController) {
if let navigationController = (controller.navigationController as? NavigationController) {
context.sharedContext.navigateToChatController(NavigateToChatControllerParams(navigationController: navigationController, context: context, chatLocation: .peer(peer)))
}
})
@ -1301,7 +1328,7 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
}
}
inviteImpl = { [weak controller] numbers in
controller?.inviteContact(presentationData: context.sharedContext.currentPresentationData.with { $0 }, numbers: numbers)
controller?.inviteContact(presentationData: environment.presentationData, numbers: numbers)
}
openAddressImpl = { [weak controller] address in
guard let _ = controller else {
@ -1309,7 +1336,7 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
}
}
openUrlImpl = { [weak controller] url in
guard let controller = controller else {
guard let controller, let context = (context as? ShareControllerAppAccountContext)?.context else {
return
}
context.sharedContext.openExternalUrl(context: context, urlContext: .generic, url: url, forceExternal: false, presentationData: context.sharedContext.currentPresentationData.with { $0 }, navigationController: controller.navigationController as? NavigationController, dismissInput: { [weak controller] in
@ -1319,7 +1346,7 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
displayCopyContextMenuImpl = { [weak controller] tag, value in
if let strongController = controller {
let presentationData = context.sharedContext.currentPresentationData.with { $0 }
let presentationData = environment.presentationData
var resultItemNode: ListViewItemNode?
let _ = strongController.frameForItemNode({ itemNode in
if let itemNode = itemNode as? ItemListTextWithLabelItemNode {
@ -1350,6 +1377,9 @@ public func deviceContactInfoController(context: AccountContext, updatedPresenta
}
}
openAvatarImpl = { [weak controller] peer in
guard let context = (context as? ShareControllerAppAccountContext)?.context else {
return
}
let avatarController = AvatarGalleryController(context: context, peer: peer, replaceRootController: { _, _ in
})
hiddenAvatarPromise.set(
@ -1413,7 +1443,7 @@ private func addContactToExisting(context: AccountContext, parentController: Vie
let _ = (dataSignal
|> deliverOnMainQueue).start(next: { peer, stableId in
guard let stableId = stableId else {
parentController.present(deviceContactInfoController(context: context, subject: .create(peer: peer?._asPeer(), contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
parentController.present(deviceContactInfoController(context: ShareControllerAppAccountContext(context: context), environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), subject: .create(peer: peer?._asPeer(), contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
}), completed: nil, cancelled: nil), in: .window(.root))
return
}
@ -1459,7 +1489,7 @@ func addContactOptionsController(context: AccountContext, peer: EnginePeer?, con
controller.setItemGroups([
ActionSheetItemGroup(items: [
ActionSheetButtonItem(title: presentationData.strings.Profile_CreateNewContact, action: { [weak controller] in
controller?.present(context.sharedContext.makeDeviceContactInfoController(context: context, subject: .create(peer: peer?._asPeer(), contactData: contactData, isSharing: peer != nil, shareViaException: false, completion: { _, _, _ in
controller?.present(context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: context), environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), subject: .create(peer: peer?._asPeer(), contactData: contactData, isSharing: peer != nil, shareViaException: false, completion: { _, _, _ in
}), completed: nil, cancelled: nil), in: .window(.root), with: ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
dismissAction()
}),
@ -1476,3 +1506,32 @@ func addContactOptionsController(context: AccountContext, peer: EnginePeer?, con
])
return controller
}
public func pushContactContextOptionsController(context: AccountContext, contextController: ContextControllerProtocol, presentationData: PresentationData, peer: EnginePeer?, contactData: DeviceContactExtendedData, parentController: ViewController, push: @escaping (ViewController) -> Void) {
var items: [ContextMenuItem] = []
items.append(
.action(ContextMenuActionItem(text: presentationData.strings.Common_Back, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Back"), color: theme.contextMenu.primaryColor) }, iconPosition: .left, action: { c, _ in
c?.popItems()
}))
)
items.append(.separator)
items.append(
.action(ContextMenuActionItem(text: presentationData.strings.Chat_Context_Phone_CreateNewContact, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) }, action: { _, f in
f(.default)
push(context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: context), environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), subject: .create(peer: peer?._asPeer(), contactData: contactData, isSharing: peer != nil, shareViaException: false, completion: { _, _, _ in
}), completed: nil, cancelled: nil))
}))
)
items.append(
.action(ContextMenuActionItem(text: presentationData.strings.Chat_Context_Phone_AddToExistingContact, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MoveToContacts"), color: theme.contextMenu.primaryColor) }, action: { [weak parentController] _, f in
f(.default)
guard let parentController else {
return
}
addContactToExisting(context: context, parentController: parentController, contactData: contactData, completion: { peer, contactId, contactData in
})
}))
)
contextController.pushItems(items: .single(ContextController.Items(content: .list(items))))
}

View File

@ -58,8 +58,8 @@ public func openAddPersonContactImpl(context: AccountContext, updatedPresentatio
if let statusSettings = statusSettings {
shareViaException = statusSettings.contains(.addExceptionWhenAddingContact)
}
pushController(deviceContactInfoController(context: context, updatedPresentationData: updatedPresentationData, subject: .create(peer: user, contactData: contactData, isSharing: true, shareViaException: shareViaException, completion: { peer, stableId, contactData in
pushController(deviceContactInfoController(context: ShareControllerAppAccountContext(context: context), environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), updatedPresentationData: updatedPresentationData, subject: .create(peer: user, contactData: contactData, isSharing: true, shareViaException: shareViaException, completion: { peer, stableId, contactData in
if let peer = peer as? TelegramUser {
completion()

View File

@ -304,18 +304,6 @@ private func collectExternalShareItems(strings: PresentationStrings, dateTimeFor
})
}
public protocol ShareControllerEnvironment: AnyObject {
var presentationData: PresentationData { get }
var updatedPresentationData: Signal<PresentationData, NoError> { get }
var isMainApp: Bool { get }
var energyUsageSettings: EnergyUsageSettings { get }
var mediaManager: MediaManager? { get }
func setAccountUserInterfaceInUse(id: AccountRecordId) -> Disposable
func donateSendMessageIntent(account: ShareControllerAccountContext, peerIds: [EnginePeer.Id])
}
public final class ShareControllerAppEnvironment: ShareControllerEnvironment {
let sharedContext: SharedAccountContext
@ -353,19 +341,6 @@ public final class ShareControllerAppEnvironment: ShareControllerEnvironment {
}
}
public protocol ShareControllerAccountContext: AnyObject {
var accountId: AccountRecordId { get }
var accountPeerId: EnginePeer.Id { get }
var stateManager: AccountStateManager { get }
var engineData: TelegramEngine.EngineData { get }
var animationCache: AnimationCache { get }
var animationRenderer: MultiAnimationRenderer { get }
var contentSettings: ContentSettings { get }
var appConfiguration: AppConfiguration { get }
func resolveInlineStickers(fileIds: [Int64]) -> Signal<[Int64: TelegramMediaFile], NoError>
}
public final class ShareControllerAppAccountContext: ShareControllerAccountContext {
public let context: AccountContext

View File

@ -349,7 +349,6 @@ final class ShareControllerNode: ViewControllerTracingNode, ASScrollViewDelegate
var disabledPeerSelected: ((EnginePeer) -> Void)?
let ready = Promise<Bool>()
private var didSetReady = false
private var controllerInteraction: ShareControllerInteraction?

View File

@ -371,6 +371,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-977967015] = { return Api.InputInvoice.parse_inputInvoiceMessage($0) }
dict[-1734841331] = { return Api.InputInvoice.parse_inputInvoicePremiumGiftCode($0) }
dict[-1020867857] = { return Api.InputInvoice.parse_inputInvoiceSlug($0) }
dict[497236696] = { return Api.InputInvoice.parse_inputInvoiceStars($0) }
dict[-122978821] = { return Api.InputMedia.parse_inputMediaContact($0) }
dict[-428884101] = { return Api.InputMedia.parse_inputMediaDice($0) }
dict[860303448] = { return Api.InputMedia.parse_inputMediaDocument($0) }
@ -459,6 +460,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1551868097] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumGiftCode($0) }
dict[369444042] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumGiveaway($0) }
dict[-1502273946] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentPremiumSubscription($0) }
dict[1326377183] = { return Api.InputStorePaymentPurpose.parse_inputStorePaymentStars($0) }
dict[1012306921] = { return Api.InputTheme.parse_inputTheme($0) }
dict[-175567375] = { return Api.InputTheme.parse_inputThemeSlug($0) }
dict[-1881255857] = { return Api.InputThemeSettings.parse_inputThemeSettings($0) }
@ -866,6 +868,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-425595208] = { return Api.SmsJob.parse_smsJob($0) }
dict[-1108478618] = { return Api.SponsoredMessage.parse_sponsoredMessage($0) }
dict[1124938064] = { return Api.SponsoredMessageReportOption.parse_sponsoredMessageReportOption($0) }
dict[198776256] = { return Api.StarsTopupOption.parse_starsTopupOption($0) }
dict[1939194818] = { return Api.StarsTransaction.parse_starsTransaction($0) }
dict[-884757282] = { return Api.StatsAbsValueAndPrev.parse_statsAbsValueAndPrev($0) }
dict[-1237848657] = { return Api.StatsDateRangeDays.parse_statsDateRangeDays($0) }
dict[-1901828938] = { return Api.StatsGraph.parse_statsGraph($0) }
@ -1030,6 +1034,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[2103604867] = { return Api.Update.parse_updateSentStoryReaction($0) }
dict[-337352679] = { return Api.Update.parse_updateServiceNotification($0) }
dict[-245208620] = { return Api.Update.parse_updateSmsJob($0) }
dict[263737752] = { return Api.Update.parse_updateStarsBalance($0) }
dict[834816008] = { return Api.Update.parse_updateStickerSets($0) }
dict[196268545] = { return Api.Update.parse_updateStickerSetsOrder($0) }
dict[738741697] = { return Api.Update.parse_updateStoriesStealthMode($0) }
@ -1292,6 +1297,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1314881805] = { return Api.payments.PaymentResult.parse_paymentResult($0) }
dict[-666824391] = { return Api.payments.PaymentResult.parse_paymentVerificationNeeded($0) }
dict[-74456004] = { return Api.payments.SavedInfo.parse_savedInfo($0) }
dict[-1930105248] = { return Api.payments.StarsStatus.parse_starsStatus($0) }
dict[-784000893] = { return Api.payments.ValidatedRequestedInfo.parse_validatedRequestedInfo($0) }
dict[541839704] = { return Api.phone.ExportedGroupCallInvite.parse_exportedGroupCallInvite($0) }
dict[-1636664659] = { return Api.phone.GroupCall.parse_groupCall($0) }
@ -1365,7 +1371,7 @@ public extension Api {
return parser(reader)
}
else {
telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
return nil
}
}
@ -1953,6 +1959,10 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.SponsoredMessageReportOption:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsTopupOption:
_1.serialize(buffer, boxed)
case let _1 as Api.StarsTransaction:
_1.serialize(buffer, boxed)
case let _1 as Api.StatsAbsValueAndPrev:
_1.serialize(buffer, boxed)
case let _1 as Api.StatsDateRangeDays:
@ -2303,6 +2313,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.payments.SavedInfo:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.StarsStatus:
_1.serialize(buffer, boxed)
case let _1 as Api.payments.ValidatedRequestedInfo:
_1.serialize(buffer, boxed)
case let _1 as Api.phone.ExportedGroupCallInvite:

View File

@ -1,3 +1,591 @@
public extension Api {
indirect enum InputMedia: TypeConstructorDescription {
case inputMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String)
case inputMediaDice(emoticon: String)
case inputMediaDocument(flags: Int32, id: Api.InputDocument, ttlSeconds: Int32?, query: String?)
case inputMediaDocumentExternal(flags: Int32, url: String, ttlSeconds: Int32?)
case inputMediaEmpty
case inputMediaGame(id: Api.InputGame)
case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?)
case inputMediaGeoPoint(geoPoint: Api.InputGeoPoint)
case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, providerData: Api.DataJSON, startParam: String?, extendedMedia: Api.InputMedia?)
case inputMediaPhoto(flags: Int32, id: Api.InputPhoto, ttlSeconds: Int32?)
case inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?)
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
case inputMediaStory(peer: Api.InputPeer, id: Int32)
case inputMediaUploadedDocument(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, mimeType: String, attributes: [Api.DocumentAttribute], stickers: [Api.InputDocument]?, ttlSeconds: Int32?)
case inputMediaUploadedPhoto(flags: Int32, file: Api.InputFile, stickers: [Api.InputDocument]?, ttlSeconds: Int32?)
case inputMediaVenue(geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String)
case inputMediaWebPage(flags: Int32, url: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputMediaContact(let phoneNumber, let firstName, let lastName, let vcard):
if boxed {
buffer.appendInt32(-122978821)
}
serializeString(phoneNumber, buffer: buffer, boxed: false)
serializeString(firstName, buffer: buffer, boxed: false)
serializeString(lastName, buffer: buffer, boxed: false)
serializeString(vcard, buffer: buffer, boxed: false)
break
case .inputMediaDice(let emoticon):
if boxed {
buffer.appendInt32(-428884101)
}
serializeString(emoticon, buffer: buffer, boxed: false)
break
case .inputMediaDocument(let flags, let id, let ttlSeconds, let query):
if boxed {
buffer.appendInt32(860303448)
}
serializeInt32(flags, buffer: buffer, boxed: false)
id.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(query!, buffer: buffer, boxed: false)}
break
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds):
if boxed {
buffer.appendInt32(-78455655)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaEmpty:
if boxed {
buffer.appendInt32(-1771768449)
}
break
case .inputMediaGame(let id):
if boxed {
buffer.appendInt32(-750828557)
}
id.serialize(buffer, true)
break
case .inputMediaGeoLive(let flags, let geoPoint, let heading, let period, let proximityNotificationRadius):
if boxed {
buffer.appendInt32(-1759532989)
}
serializeInt32(flags, buffer: buffer, boxed: false)
geoPoint.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(heading!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(period!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)}
break
case .inputMediaGeoPoint(let geoPoint):
if boxed {
buffer.appendInt32(-104578748)
}
geoPoint.serialize(buffer, true)
break
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia):
if boxed {
buffer.appendInt32(-1900697899)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(title, buffer: buffer, boxed: false)
serializeString(description, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)}
invoice.serialize(buffer, true)
serializeBytes(payload, buffer: buffer, boxed: false)
serializeString(provider, buffer: buffer, boxed: false)
providerData.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {extendedMedia!.serialize(buffer, true)}
break
case .inputMediaPhoto(let flags, let id, let ttlSeconds):
if boxed {
buffer.appendInt32(-1279654347)
}
serializeInt32(flags, buffer: buffer, boxed: false)
id.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds):
if boxed {
buffer.appendInt32(-440664550)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaPoll(let flags, let poll, let correctAnswers, let solution, let solutionEntities):
if boxed {
buffer.appendInt32(261416433)
}
serializeInt32(flags, buffer: buffer, boxed: false)
poll.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(correctAnswers!.count))
for item in correctAnswers! {
serializeBytes(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeString(solution!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(solutionEntities!.count))
for item in solutionEntities! {
item.serialize(buffer, true)
}}
break
case .inputMediaStory(let peer, let id):
if boxed {
buffer.appendInt32(-1979852936)
}
peer.serialize(buffer, true)
serializeInt32(id, buffer: buffer, boxed: false)
break
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let ttlSeconds):
if boxed {
buffer.appendInt32(1530447553)
}
serializeInt32(flags, buffer: buffer, boxed: false)
file.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {thumb!.serialize(buffer, true)}
serializeString(mimeType, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(attributes.count))
for item in attributes {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(stickers!.count))
for item in stickers! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
if boxed {
buffer.appendInt32(505969924)
}
serializeInt32(flags, buffer: buffer, boxed: false)
file.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(stickers!.count))
for item in stickers! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType):
if boxed {
buffer.appendInt32(-1052959727)
}
geoPoint.serialize(buffer, true)
serializeString(title, buffer: buffer, boxed: false)
serializeString(address, buffer: buffer, boxed: false)
serializeString(provider, buffer: buffer, boxed: false)
serializeString(venueId, buffer: buffer, boxed: false)
serializeString(venueType, buffer: buffer, boxed: false)
break
case .inputMediaWebPage(let flags, let url):
if boxed {
buffer.appendInt32(-1038383031)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputMediaContact(let phoneNumber, let firstName, let lastName, let vcard):
return ("inputMediaContact", [("phoneNumber", phoneNumber as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("vcard", vcard as Any)])
case .inputMediaDice(let emoticon):
return ("inputMediaDice", [("emoticon", emoticon as Any)])
case .inputMediaDocument(let flags, let id, let ttlSeconds, let query):
return ("inputMediaDocument", [("flags", flags as Any), ("id", id as Any), ("ttlSeconds", ttlSeconds as Any), ("query", query as Any)])
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds):
return ("inputMediaDocumentExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaEmpty:
return ("inputMediaEmpty", [])
case .inputMediaGame(let id):
return ("inputMediaGame", [("id", id as Any)])
case .inputMediaGeoLive(let flags, let geoPoint, let heading, let period, let proximityNotificationRadius):
return ("inputMediaGeoLive", [("flags", flags as Any), ("geoPoint", geoPoint as Any), ("heading", heading as Any), ("period", period as Any), ("proximityNotificationRadius", proximityNotificationRadius as Any)])
case .inputMediaGeoPoint(let geoPoint):
return ("inputMediaGeoPoint", [("geoPoint", geoPoint as Any)])
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia):
return ("inputMediaInvoice", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("payload", payload as Any), ("provider", provider as Any), ("providerData", providerData as Any), ("startParam", startParam as Any), ("extendedMedia", extendedMedia as Any)])
case .inputMediaPhoto(let flags, let id, let ttlSeconds):
return ("inputMediaPhoto", [("flags", flags as Any), ("id", id as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds):
return ("inputMediaPhotoExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaPoll(let flags, let poll, let correctAnswers, let solution, let solutionEntities):
return ("inputMediaPoll", [("flags", flags as Any), ("poll", poll as Any), ("correctAnswers", correctAnswers as Any), ("solution", solution as Any), ("solutionEntities", solutionEntities as Any)])
case .inputMediaStory(let peer, let id):
return ("inputMediaStory", [("peer", peer as Any), ("id", id as Any)])
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let ttlSeconds):
return ("inputMediaUploadedDocument", [("flags", flags as Any), ("file", file as Any), ("thumb", thumb as Any), ("mimeType", mimeType as Any), ("attributes", attributes as Any), ("stickers", stickers as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
return ("inputMediaUploadedPhoto", [("flags", flags as Any), ("file", file as Any), ("stickers", stickers as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType):
return ("inputMediaVenue", [("geoPoint", geoPoint as Any), ("title", title as Any), ("address", address as Any), ("provider", provider as Any), ("venueId", venueId as Any), ("venueType", venueType as Any)])
case .inputMediaWebPage(let flags, let url):
return ("inputMediaWebPage", [("flags", flags as Any), ("url", url as Any)])
}
}
public static func parse_inputMediaContact(_ reader: BufferReader) -> InputMedia? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
_4 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputMedia.inputMediaContact(phoneNumber: _1!, firstName: _2!, lastName: _3!, vcard: _4!)
}
else {
return nil
}
}
public static func parse_inputMediaDice(_ reader: BufferReader) -> InputMedia? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputMedia.inputMediaDice(emoticon: _1!)
}
else {
return nil
}
}
public static func parse_inputMediaDocument(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputDocument?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputDocument
}
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputMedia.inputMediaDocument(flags: _1!, id: _2!, ttlSeconds: _3, query: _4)
}
else {
return nil
}
}
public static func parse_inputMediaDocumentExternal(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputMedia.inputMediaDocumentExternal(flags: _1!, url: _2!, ttlSeconds: _3)
}
else {
return nil
}
}
public static func parse_inputMediaEmpty(_ reader: BufferReader) -> InputMedia? {
return Api.InputMedia.inputMediaEmpty
}
public static func parse_inputMediaGame(_ reader: BufferReader) -> InputMedia? {
var _1: Api.InputGame?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputGame
}
let _c1 = _1 != nil
if _c1 {
return Api.InputMedia.inputMediaGame(id: _1!)
}
else {
return nil
}
}
public static func parse_inputMediaGeoLive(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputGeoPoint?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
}
var _3: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() }
var _4: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
var _5: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_5 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.InputMedia.inputMediaGeoLive(flags: _1!, geoPoint: _2!, heading: _3, period: _4, proximityNotificationRadius: _5)
}
else {
return nil
}
}
public static func parse_inputMediaGeoPoint(_ reader: BufferReader) -> InputMedia? {
var _1: Api.InputGeoPoint?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
}
let _c1 = _1 != nil
if _c1 {
return Api.InputMedia.inputMediaGeoPoint(geoPoint: _1!)
}
else {
return nil
}
}
public static func parse_inputMediaInvoice(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: Api.InputWebDocument?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.InputWebDocument
} }
var _5: Api.Invoice?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Invoice
}
var _6: Buffer?
_6 = parseBytes(reader)
var _7: String?
_7 = parseString(reader)
var _8: Api.DataJSON?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
var _9: String?
if Int(_1!) & Int(1 << 1) != 0 {_9 = parseString(reader) }
var _10: Api.InputMedia?
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.InputMedia
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil
let _c10 = (Int(_1!) & Int(1 << 2) == 0) || _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
return Api.InputMedia.inputMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, invoice: _5!, payload: _6!, provider: _7!, providerData: _8!, startParam: _9, extendedMedia: _10)
}
else {
return nil
}
}
public static func parse_inputMediaPhoto(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputPhoto?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputPhoto
}
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputMedia.inputMediaPhoto(flags: _1!, id: _2!, ttlSeconds: _3)
}
else {
return nil
}
}
public static func parse_inputMediaPhotoExternal(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputMedia.inputMediaPhotoExternal(flags: _1!, url: _2!, ttlSeconds: _3)
}
else {
return nil
}
}
public static func parse_inputMediaPoll(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Poll?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Poll
}
var _3: [Buffer]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self)
} }
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
var _5: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.InputMedia.inputMediaPoll(flags: _1!, poll: _2!, correctAnswers: _3, solution: _4, solutionEntities: _5)
}
else {
return nil
}
}
public static func parse_inputMediaStory(_ reader: BufferReader) -> InputMedia? {
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.InputMedia.inputMediaStory(peer: _1!, id: _2!)
}
else {
return nil
}
}
public static func parse_inputMediaUploadedDocument(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputFile?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputFile
}
var _3: Api.InputFile?
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.InputFile
} }
var _4: String?
_4 = parseString(reader)
var _5: [Api.DocumentAttribute]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self)
}
var _6: [Api.InputDocument]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputDocument.self)
} }
var _7: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_7 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.InputMedia.inputMediaUploadedDocument(flags: _1!, file: _2!, thumb: _3, mimeType: _4!, attributes: _5!, stickers: _6, ttlSeconds: _7)
}
else {
return nil
}
}
public static func parse_inputMediaUploadedPhoto(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputFile?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputFile
}
var _3: [Api.InputDocument]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputDocument.self)
} }
var _4: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputMedia.inputMediaUploadedPhoto(flags: _1!, file: _2!, stickers: _3, ttlSeconds: _4)
}
else {
return nil
}
}
public static func parse_inputMediaVenue(_ reader: BufferReader) -> InputMedia? {
var _1: Api.InputGeoPoint?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
}
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
_4 = parseString(reader)
var _5: String?
_5 = parseString(reader)
var _6: String?
_6 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.InputMedia.inputMediaVenue(geoPoint: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!, venueType: _6!)
}
else {
return nil
}
}
public static func parse_inputMediaWebPage(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputMedia.inputMediaWebPage(flags: _1!, url: _2!)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputMessage: TypeConstructorDescription {
case inputMessageCallbackQuery(id: Int32, queryId: Int64)
@ -468,323 +1056,3 @@ public extension Api {
}
}
public extension Api {
enum InputPeerNotifySettings: TypeConstructorDescription {
case inputPeerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, sound: Api.NotificationSound?, storiesMuted: Api.Bool?, storiesHideSender: Api.Bool?, storiesSound: Api.NotificationSound?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPeerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let sound, let storiesMuted, let storiesHideSender, let storiesSound):
if boxed {
buffer.appendInt32(-892638494)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {showPreviews!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {silent!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(muteUntil!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {sound!.serialize(buffer, true)}
if Int(flags) & Int(1 << 6) != 0 {storiesMuted!.serialize(buffer, true)}
if Int(flags) & Int(1 << 7) != 0 {storiesHideSender!.serialize(buffer, true)}
if Int(flags) & Int(1 << 8) != 0 {storiesSound!.serialize(buffer, true)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPeerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let sound, let storiesMuted, let storiesHideSender, let storiesSound):
return ("inputPeerNotifySettings", [("flags", flags as Any), ("showPreviews", showPreviews as Any), ("silent", silent as Any), ("muteUntil", muteUntil as Any), ("sound", sound as Any), ("storiesMuted", storiesMuted as Any), ("storiesHideSender", storiesHideSender as Any), ("storiesSound", storiesSound as Any)])
}
}
public static func parse_inputPeerNotifySettings(_ reader: BufferReader) -> InputPeerNotifySettings? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Bool?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _3: Api.Bool?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _4: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
var _5: Api.NotificationSound?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
var _6: Api.Bool?
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _7: Api.Bool?
if Int(_1!) & Int(1 << 7) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _8: Api.NotificationSound?
if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 6) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 7) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 8) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: _1!, showPreviews: _2, silent: _3, muteUntil: _4, sound: _5, storiesMuted: _6, storiesHideSender: _7, storiesSound: _8)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputPhoneCall: TypeConstructorDescription {
case inputPhoneCall(id: Int64, accessHash: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPhoneCall(let id, let accessHash):
if boxed {
buffer.appendInt32(506920429)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPhoneCall(let id, let accessHash):
return ("inputPhoneCall", [("id", id as Any), ("accessHash", accessHash as Any)])
}
}
public static func parse_inputPhoneCall(_ reader: BufferReader) -> InputPhoneCall? {
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.InputPhoneCall.inputPhoneCall(id: _1!, accessHash: _2!)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputPhoto: TypeConstructorDescription {
case inputPhoto(id: Int64, accessHash: Int64, fileReference: Buffer)
case inputPhotoEmpty
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPhoto(let id, let accessHash, let fileReference):
if boxed {
buffer.appendInt32(1001634122)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeBytes(fileReference, buffer: buffer, boxed: false)
break
case .inputPhotoEmpty:
if boxed {
buffer.appendInt32(483901197)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPhoto(let id, let accessHash, let fileReference):
return ("inputPhoto", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any)])
case .inputPhotoEmpty:
return ("inputPhotoEmpty", [])
}
}
public static func parse_inputPhoto(_ reader: BufferReader) -> InputPhoto? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
var _3: Buffer?
_3 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputPhoto.inputPhoto(id: _1!, accessHash: _2!, fileReference: _3!)
}
else {
return nil
}
}
public static func parse_inputPhotoEmpty(_ reader: BufferReader) -> InputPhoto? {
return Api.InputPhoto.inputPhotoEmpty
}
}
}
public extension Api {
enum InputPrivacyKey: TypeConstructorDescription {
case inputPrivacyKeyAbout
case inputPrivacyKeyAddedByPhone
case inputPrivacyKeyBirthday
case inputPrivacyKeyChatInvite
case inputPrivacyKeyForwards
case inputPrivacyKeyPhoneCall
case inputPrivacyKeyPhoneNumber
case inputPrivacyKeyPhoneP2P
case inputPrivacyKeyProfilePhoto
case inputPrivacyKeyStatusTimestamp
case inputPrivacyKeyVoiceMessages
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPrivacyKeyAbout:
if boxed {
buffer.appendInt32(941870144)
}
break
case .inputPrivacyKeyAddedByPhone:
if boxed {
buffer.appendInt32(-786326563)
}
break
case .inputPrivacyKeyBirthday:
if boxed {
buffer.appendInt32(-698740276)
}
break
case .inputPrivacyKeyChatInvite:
if boxed {
buffer.appendInt32(-1107622874)
}
break
case .inputPrivacyKeyForwards:
if boxed {
buffer.appendInt32(-1529000952)
}
break
case .inputPrivacyKeyPhoneCall:
if boxed {
buffer.appendInt32(-88417185)
}
break
case .inputPrivacyKeyPhoneNumber:
if boxed {
buffer.appendInt32(55761658)
}
break
case .inputPrivacyKeyPhoneP2P:
if boxed {
buffer.appendInt32(-610373422)
}
break
case .inputPrivacyKeyProfilePhoto:
if boxed {
buffer.appendInt32(1461304012)
}
break
case .inputPrivacyKeyStatusTimestamp:
if boxed {
buffer.appendInt32(1335282456)
}
break
case .inputPrivacyKeyVoiceMessages:
if boxed {
buffer.appendInt32(-1360618136)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPrivacyKeyAbout:
return ("inputPrivacyKeyAbout", [])
case .inputPrivacyKeyAddedByPhone:
return ("inputPrivacyKeyAddedByPhone", [])
case .inputPrivacyKeyBirthday:
return ("inputPrivacyKeyBirthday", [])
case .inputPrivacyKeyChatInvite:
return ("inputPrivacyKeyChatInvite", [])
case .inputPrivacyKeyForwards:
return ("inputPrivacyKeyForwards", [])
case .inputPrivacyKeyPhoneCall:
return ("inputPrivacyKeyPhoneCall", [])
case .inputPrivacyKeyPhoneNumber:
return ("inputPrivacyKeyPhoneNumber", [])
case .inputPrivacyKeyPhoneP2P:
return ("inputPrivacyKeyPhoneP2P", [])
case .inputPrivacyKeyProfilePhoto:
return ("inputPrivacyKeyProfilePhoto", [])
case .inputPrivacyKeyStatusTimestamp:
return ("inputPrivacyKeyStatusTimestamp", [])
case .inputPrivacyKeyVoiceMessages:
return ("inputPrivacyKeyVoiceMessages", [])
}
}
public static func parse_inputPrivacyKeyAbout(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyAbout
}
public static func parse_inputPrivacyKeyAddedByPhone(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyAddedByPhone
}
public static func parse_inputPrivacyKeyBirthday(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyBirthday
}
public static func parse_inputPrivacyKeyChatInvite(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyChatInvite
}
public static func parse_inputPrivacyKeyForwards(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyForwards
}
public static func parse_inputPrivacyKeyPhoneCall(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyPhoneCall
}
public static func parse_inputPrivacyKeyPhoneNumber(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyPhoneNumber
}
public static func parse_inputPrivacyKeyPhoneP2P(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyPhoneP2P
}
public static func parse_inputPrivacyKeyProfilePhoto(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyProfilePhoto
}
public static func parse_inputPrivacyKeyStatusTimestamp(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyStatusTimestamp
}
public static func parse_inputPrivacyKeyVoiceMessages(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyVoiceMessages
}
}
}

View File

@ -1,3 +1,323 @@
public extension Api {
enum InputPeerNotifySettings: TypeConstructorDescription {
case inputPeerNotifySettings(flags: Int32, showPreviews: Api.Bool?, silent: Api.Bool?, muteUntil: Int32?, sound: Api.NotificationSound?, storiesMuted: Api.Bool?, storiesHideSender: Api.Bool?, storiesSound: Api.NotificationSound?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPeerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let sound, let storiesMuted, let storiesHideSender, let storiesSound):
if boxed {
buffer.appendInt32(-892638494)
}
serializeInt32(flags, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {showPreviews!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {silent!.serialize(buffer, true)}
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(muteUntil!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {sound!.serialize(buffer, true)}
if Int(flags) & Int(1 << 6) != 0 {storiesMuted!.serialize(buffer, true)}
if Int(flags) & Int(1 << 7) != 0 {storiesHideSender!.serialize(buffer, true)}
if Int(flags) & Int(1 << 8) != 0 {storiesSound!.serialize(buffer, true)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPeerNotifySettings(let flags, let showPreviews, let silent, let muteUntil, let sound, let storiesMuted, let storiesHideSender, let storiesSound):
return ("inputPeerNotifySettings", [("flags", flags as Any), ("showPreviews", showPreviews as Any), ("silent", silent as Any), ("muteUntil", muteUntil as Any), ("sound", sound as Any), ("storiesMuted", storiesMuted as Any), ("storiesHideSender", storiesHideSender as Any), ("storiesSound", storiesSound as Any)])
}
}
public static func parse_inputPeerNotifySettings(_ reader: BufferReader) -> InputPeerNotifySettings? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Bool?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _3: Api.Bool?
if Int(_1!) & Int(1 << 1) != 0 {if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _4: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_4 = reader.readInt32() }
var _5: Api.NotificationSound?
if Int(_1!) & Int(1 << 3) != 0 {if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
var _6: Api.Bool?
if Int(_1!) & Int(1 << 6) != 0 {if let signature = reader.readInt32() {
_6 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _7: Api.Bool?
if Int(_1!) & Int(1 << 7) != 0 {if let signature = reader.readInt32() {
_7 = Api.parse(reader, signature: signature) as? Api.Bool
} }
var _8: Api.NotificationSound?
if Int(_1!) & Int(1 << 8) != 0 {if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.NotificationSound
} }
let _c1 = _1 != nil
let _c2 = (Int(_1!) & Int(1 << 0) == 0) || _2 != nil
let _c3 = (Int(_1!) & Int(1 << 1) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 2) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
let _c6 = (Int(_1!) & Int(1 << 6) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 7) == 0) || _7 != nil
let _c8 = (Int(_1!) & Int(1 << 8) == 0) || _8 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 {
return Api.InputPeerNotifySettings.inputPeerNotifySettings(flags: _1!, showPreviews: _2, silent: _3, muteUntil: _4, sound: _5, storiesMuted: _6, storiesHideSender: _7, storiesSound: _8)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputPhoneCall: TypeConstructorDescription {
case inputPhoneCall(id: Int64, accessHash: Int64)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPhoneCall(let id, let accessHash):
if boxed {
buffer.appendInt32(506920429)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPhoneCall(let id, let accessHash):
return ("inputPhoneCall", [("id", id as Any), ("accessHash", accessHash as Any)])
}
}
public static func parse_inputPhoneCall(_ reader: BufferReader) -> InputPhoneCall? {
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.InputPhoneCall.inputPhoneCall(id: _1!, accessHash: _2!)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputPhoto: TypeConstructorDescription {
case inputPhoto(id: Int64, accessHash: Int64, fileReference: Buffer)
case inputPhotoEmpty
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPhoto(let id, let accessHash, let fileReference):
if boxed {
buffer.appendInt32(1001634122)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
serializeBytes(fileReference, buffer: buffer, boxed: false)
break
case .inputPhotoEmpty:
if boxed {
buffer.appendInt32(483901197)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPhoto(let id, let accessHash, let fileReference):
return ("inputPhoto", [("id", id as Any), ("accessHash", accessHash as Any), ("fileReference", fileReference as Any)])
case .inputPhotoEmpty:
return ("inputPhotoEmpty", [])
}
}
public static func parse_inputPhoto(_ reader: BufferReader) -> InputPhoto? {
var _1: Int64?
_1 = reader.readInt64()
var _2: Int64?
_2 = reader.readInt64()
var _3: Buffer?
_3 = parseBytes(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputPhoto.inputPhoto(id: _1!, accessHash: _2!, fileReference: _3!)
}
else {
return nil
}
}
public static func parse_inputPhotoEmpty(_ reader: BufferReader) -> InputPhoto? {
return Api.InputPhoto.inputPhotoEmpty
}
}
}
public extension Api {
enum InputPrivacyKey: TypeConstructorDescription {
case inputPrivacyKeyAbout
case inputPrivacyKeyAddedByPhone
case inputPrivacyKeyBirthday
case inputPrivacyKeyChatInvite
case inputPrivacyKeyForwards
case inputPrivacyKeyPhoneCall
case inputPrivacyKeyPhoneNumber
case inputPrivacyKeyPhoneP2P
case inputPrivacyKeyProfilePhoto
case inputPrivacyKeyStatusTimestamp
case inputPrivacyKeyVoiceMessages
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPrivacyKeyAbout:
if boxed {
buffer.appendInt32(941870144)
}
break
case .inputPrivacyKeyAddedByPhone:
if boxed {
buffer.appendInt32(-786326563)
}
break
case .inputPrivacyKeyBirthday:
if boxed {
buffer.appendInt32(-698740276)
}
break
case .inputPrivacyKeyChatInvite:
if boxed {
buffer.appendInt32(-1107622874)
}
break
case .inputPrivacyKeyForwards:
if boxed {
buffer.appendInt32(-1529000952)
}
break
case .inputPrivacyKeyPhoneCall:
if boxed {
buffer.appendInt32(-88417185)
}
break
case .inputPrivacyKeyPhoneNumber:
if boxed {
buffer.appendInt32(55761658)
}
break
case .inputPrivacyKeyPhoneP2P:
if boxed {
buffer.appendInt32(-610373422)
}
break
case .inputPrivacyKeyProfilePhoto:
if boxed {
buffer.appendInt32(1461304012)
}
break
case .inputPrivacyKeyStatusTimestamp:
if boxed {
buffer.appendInt32(1335282456)
}
break
case .inputPrivacyKeyVoiceMessages:
if boxed {
buffer.appendInt32(-1360618136)
}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputPrivacyKeyAbout:
return ("inputPrivacyKeyAbout", [])
case .inputPrivacyKeyAddedByPhone:
return ("inputPrivacyKeyAddedByPhone", [])
case .inputPrivacyKeyBirthday:
return ("inputPrivacyKeyBirthday", [])
case .inputPrivacyKeyChatInvite:
return ("inputPrivacyKeyChatInvite", [])
case .inputPrivacyKeyForwards:
return ("inputPrivacyKeyForwards", [])
case .inputPrivacyKeyPhoneCall:
return ("inputPrivacyKeyPhoneCall", [])
case .inputPrivacyKeyPhoneNumber:
return ("inputPrivacyKeyPhoneNumber", [])
case .inputPrivacyKeyPhoneP2P:
return ("inputPrivacyKeyPhoneP2P", [])
case .inputPrivacyKeyProfilePhoto:
return ("inputPrivacyKeyProfilePhoto", [])
case .inputPrivacyKeyStatusTimestamp:
return ("inputPrivacyKeyStatusTimestamp", [])
case .inputPrivacyKeyVoiceMessages:
return ("inputPrivacyKeyVoiceMessages", [])
}
}
public static func parse_inputPrivacyKeyAbout(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyAbout
}
public static func parse_inputPrivacyKeyAddedByPhone(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyAddedByPhone
}
public static func parse_inputPrivacyKeyBirthday(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyBirthday
}
public static func parse_inputPrivacyKeyChatInvite(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyChatInvite
}
public static func parse_inputPrivacyKeyForwards(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyForwards
}
public static func parse_inputPrivacyKeyPhoneCall(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyPhoneCall
}
public static func parse_inputPrivacyKeyPhoneNumber(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyPhoneNumber
}
public static func parse_inputPrivacyKeyPhoneP2P(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyPhoneP2P
}
public static func parse_inputPrivacyKeyProfilePhoto(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyProfilePhoto
}
public static func parse_inputPrivacyKeyStatusTimestamp(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyStatusTimestamp
}
public static func parse_inputPrivacyKeyVoiceMessages(_ reader: BufferReader) -> InputPrivacyKey? {
return Api.InputPrivacyKey.inputPrivacyKeyVoiceMessages
}
}
}
public extension Api {
enum InputPrivacyRule: TypeConstructorDescription {
case inputPrivacyValueAllowAll
@ -508,355 +828,3 @@ public extension Api {
}
}
public extension Api {
indirect enum InputSingleMedia: TypeConstructorDescription {
case inputSingleMedia(flags: Int32, media: Api.InputMedia, randomId: Int64, message: String, entities: [Api.MessageEntity]?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputSingleMedia(let flags, let media, let randomId, let message, let entities):
if boxed {
buffer.appendInt32(482797855)
}
serializeInt32(flags, buffer: buffer, boxed: false)
media.serialize(buffer, true)
serializeInt64(randomId, buffer: buffer, boxed: false)
serializeString(message, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(entities!.count))
for item in entities! {
item.serialize(buffer, true)
}}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputSingleMedia(let flags, let media, let randomId, let message, let entities):
return ("inputSingleMedia", [("flags", flags as Any), ("media", media as Any), ("randomId", randomId as Any), ("message", message as Any), ("entities", entities as Any)])
}
}
public static func parse_inputSingleMedia(_ reader: BufferReader) -> InputSingleMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputMedia?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputMedia
}
var _3: Int64?
_3 = reader.readInt64()
var _4: String?
_4 = parseString(reader)
var _5: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = (Int(_1!) & Int(1 << 0) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.InputSingleMedia.inputSingleMedia(flags: _1!, media: _2!, randomId: _3!, message: _4!, entities: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputStickerSet: TypeConstructorDescription {
case inputStickerSetAnimatedEmoji
case inputStickerSetAnimatedEmojiAnimations
case inputStickerSetDice(emoticon: String)
case inputStickerSetEmojiChannelDefaultStatuses
case inputStickerSetEmojiDefaultStatuses
case inputStickerSetEmojiDefaultTopicIcons
case inputStickerSetEmojiGenericAnimations
case inputStickerSetEmpty
case inputStickerSetID(id: Int64, accessHash: Int64)
case inputStickerSetPremiumGifts
case inputStickerSetShortName(shortName: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputStickerSetAnimatedEmoji:
if boxed {
buffer.appendInt32(42402760)
}
break
case .inputStickerSetAnimatedEmojiAnimations:
if boxed {
buffer.appendInt32(215889721)
}
break
case .inputStickerSetDice(let emoticon):
if boxed {
buffer.appendInt32(-427863538)
}
serializeString(emoticon, buffer: buffer, boxed: false)
break
case .inputStickerSetEmojiChannelDefaultStatuses:
if boxed {
buffer.appendInt32(1232373075)
}
break
case .inputStickerSetEmojiDefaultStatuses:
if boxed {
buffer.appendInt32(701560302)
}
break
case .inputStickerSetEmojiDefaultTopicIcons:
if boxed {
buffer.appendInt32(1153562857)
}
break
case .inputStickerSetEmojiGenericAnimations:
if boxed {
buffer.appendInt32(80008398)
}
break
case .inputStickerSetEmpty:
if boxed {
buffer.appendInt32(-4838507)
}
break
case .inputStickerSetID(let id, let accessHash):
if boxed {
buffer.appendInt32(-1645763991)
}
serializeInt64(id, buffer: buffer, boxed: false)
serializeInt64(accessHash, buffer: buffer, boxed: false)
break
case .inputStickerSetPremiumGifts:
if boxed {
buffer.appendInt32(-930399486)
}
break
case .inputStickerSetShortName(let shortName):
if boxed {
buffer.appendInt32(-2044933984)
}
serializeString(shortName, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputStickerSetAnimatedEmoji:
return ("inputStickerSetAnimatedEmoji", [])
case .inputStickerSetAnimatedEmojiAnimations:
return ("inputStickerSetAnimatedEmojiAnimations", [])
case .inputStickerSetDice(let emoticon):
return ("inputStickerSetDice", [("emoticon", emoticon as Any)])
case .inputStickerSetEmojiChannelDefaultStatuses:
return ("inputStickerSetEmojiChannelDefaultStatuses", [])
case .inputStickerSetEmojiDefaultStatuses:
return ("inputStickerSetEmojiDefaultStatuses", [])
case .inputStickerSetEmojiDefaultTopicIcons:
return ("inputStickerSetEmojiDefaultTopicIcons", [])
case .inputStickerSetEmojiGenericAnimations:
return ("inputStickerSetEmojiGenericAnimations", [])
case .inputStickerSetEmpty:
return ("inputStickerSetEmpty", [])
case .inputStickerSetID(let id, let accessHash):
return ("inputStickerSetID", [("id", id as Any), ("accessHash", accessHash as Any)])
case .inputStickerSetPremiumGifts:
return ("inputStickerSetPremiumGifts", [])
case .inputStickerSetShortName(let shortName):
return ("inputStickerSetShortName", [("shortName", shortName as Any)])
}
}
public static func parse_inputStickerSetAnimatedEmoji(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetAnimatedEmoji
}
public static func parse_inputStickerSetAnimatedEmojiAnimations(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetAnimatedEmojiAnimations
}
public static func parse_inputStickerSetDice(_ reader: BufferReader) -> InputStickerSet? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputStickerSet.inputStickerSetDice(emoticon: _1!)
}
else {
return nil
}
}
public static func parse_inputStickerSetEmojiChannelDefaultStatuses(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetEmojiChannelDefaultStatuses
}
public static func parse_inputStickerSetEmojiDefaultStatuses(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetEmojiDefaultStatuses
}
public static func parse_inputStickerSetEmojiDefaultTopicIcons(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetEmojiDefaultTopicIcons
}
public static func parse_inputStickerSetEmojiGenericAnimations(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetEmojiGenericAnimations
}
public static func parse_inputStickerSetEmpty(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetEmpty
}
public static func parse_inputStickerSetID(_ reader: BufferReader) -> InputStickerSet? {
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.InputStickerSet.inputStickerSetID(id: _1!, accessHash: _2!)
}
else {
return nil
}
}
public static func parse_inputStickerSetPremiumGifts(_ reader: BufferReader) -> InputStickerSet? {
return Api.InputStickerSet.inputStickerSetPremiumGifts
}
public static func parse_inputStickerSetShortName(_ reader: BufferReader) -> InputStickerSet? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputStickerSet.inputStickerSetShortName(shortName: _1!)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputStickerSetItem: TypeConstructorDescription {
case inputStickerSetItem(flags: Int32, document: Api.InputDocument, emoji: String, maskCoords: Api.MaskCoords?, keywords: String?)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputStickerSetItem(let flags, let document, let emoji, let maskCoords, let keywords):
if boxed {
buffer.appendInt32(853188252)
}
serializeInt32(flags, buffer: buffer, boxed: false)
document.serialize(buffer, true)
serializeString(emoji, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {maskCoords!.serialize(buffer, true)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(keywords!, buffer: buffer, boxed: false)}
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputStickerSetItem(let flags, let document, let emoji, let maskCoords, let keywords):
return ("inputStickerSetItem", [("flags", flags as Any), ("document", document as Any), ("emoji", emoji as Any), ("maskCoords", maskCoords as Any), ("keywords", keywords as Any)])
}
}
public static func parse_inputStickerSetItem(_ reader: BufferReader) -> InputStickerSetItem? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputDocument?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputDocument
}
var _3: String?
_3 = parseString(reader)
var _4: Api.MaskCoords?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.MaskCoords
} }
var _5: String?
if Int(_1!) & Int(1 << 1) != 0 {_5 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.InputStickerSetItem.inputStickerSetItem(flags: _1!, document: _2!, emoji: _3!, maskCoords: _4, keywords: _5)
}
else {
return nil
}
}
}
}
public extension Api {
enum InputStickeredMedia: TypeConstructorDescription {
case inputStickeredMediaDocument(id: Api.InputDocument)
case inputStickeredMediaPhoto(id: Api.InputPhoto)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputStickeredMediaDocument(let id):
if boxed {
buffer.appendInt32(70813275)
}
id.serialize(buffer, true)
break
case .inputStickeredMediaPhoto(let id):
if boxed {
buffer.appendInt32(1251549527)
}
id.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputStickeredMediaDocument(let id):
return ("inputStickeredMediaDocument", [("id", id as Any)])
case .inputStickeredMediaPhoto(let id):
return ("inputStickeredMediaPhoto", [("id", id as Any)])
}
}
public static func parse_inputStickeredMediaDocument(_ reader: BufferReader) -> InputStickeredMedia? {
var _1: Api.InputDocument?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputDocument
}
let _c1 = _1 != nil
if _c1 {
return Api.InputStickeredMedia.inputStickeredMediaDocument(id: _1!)
}
else {
return nil
}
}
public static func parse_inputStickeredMediaPhoto(_ reader: BufferReader) -> InputStickeredMedia? {
var _1: Api.InputPhoto?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputPhoto
}
let _c1 = _1 != nil
if _c1 {
return Api.InputStickeredMedia.inputStickeredMediaPhoto(id: _1!)
}
else {
return nil
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -911,6 +911,7 @@ public extension Api {
case inputInvoiceMessage(peer: Api.InputPeer, msgId: Int32)
case inputInvoicePremiumGiftCode(purpose: Api.InputStorePaymentPurpose, option: Api.PremiumGiftCodeOption)
case inputInvoiceSlug(slug: String)
case inputInvoiceStars(option: Api.StarsTopupOption)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
@ -934,6 +935,12 @@ public extension Api {
}
serializeString(slug, buffer: buffer, boxed: false)
break
case .inputInvoiceStars(let option):
if boxed {
buffer.appendInt32(497236696)
}
option.serialize(buffer, true)
break
}
}
@ -945,6 +952,8 @@ public extension Api {
return ("inputInvoicePremiumGiftCode", [("purpose", purpose as Any), ("option", option as Any)])
case .inputInvoiceSlug(let slug):
return ("inputInvoiceSlug", [("slug", slug as Any)])
case .inputInvoiceStars(let option):
return ("inputInvoiceStars", [("option", option as Any)])
}
}
@ -993,589 +1002,14 @@ public extension Api {
return nil
}
}
}
}
public extension Api {
indirect enum InputMedia: TypeConstructorDescription {
case inputMediaContact(phoneNumber: String, firstName: String, lastName: String, vcard: String)
case inputMediaDice(emoticon: String)
case inputMediaDocument(flags: Int32, id: Api.InputDocument, ttlSeconds: Int32?, query: String?)
case inputMediaDocumentExternal(flags: Int32, url: String, ttlSeconds: Int32?)
case inputMediaEmpty
case inputMediaGame(id: Api.InputGame)
case inputMediaGeoLive(flags: Int32, geoPoint: Api.InputGeoPoint, heading: Int32?, period: Int32?, proximityNotificationRadius: Int32?)
case inputMediaGeoPoint(geoPoint: Api.InputGeoPoint)
case inputMediaInvoice(flags: Int32, title: String, description: String, photo: Api.InputWebDocument?, invoice: Api.Invoice, payload: Buffer, provider: String, providerData: Api.DataJSON, startParam: String?, extendedMedia: Api.InputMedia?)
case inputMediaPhoto(flags: Int32, id: Api.InputPhoto, ttlSeconds: Int32?)
case inputMediaPhotoExternal(flags: Int32, url: String, ttlSeconds: Int32?)
case inputMediaPoll(flags: Int32, poll: Api.Poll, correctAnswers: [Buffer]?, solution: String?, solutionEntities: [Api.MessageEntity]?)
case inputMediaStory(peer: Api.InputPeer, id: Int32)
case inputMediaUploadedDocument(flags: Int32, file: Api.InputFile, thumb: Api.InputFile?, mimeType: String, attributes: [Api.DocumentAttribute], stickers: [Api.InputDocument]?, ttlSeconds: Int32?)
case inputMediaUploadedPhoto(flags: Int32, file: Api.InputFile, stickers: [Api.InputDocument]?, ttlSeconds: Int32?)
case inputMediaVenue(geoPoint: Api.InputGeoPoint, title: String, address: String, provider: String, venueId: String, venueType: String)
case inputMediaWebPage(flags: Int32, url: String)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputMediaContact(let phoneNumber, let firstName, let lastName, let vcard):
if boxed {
buffer.appendInt32(-122978821)
}
serializeString(phoneNumber, buffer: buffer, boxed: false)
serializeString(firstName, buffer: buffer, boxed: false)
serializeString(lastName, buffer: buffer, boxed: false)
serializeString(vcard, buffer: buffer, boxed: false)
break
case .inputMediaDice(let emoticon):
if boxed {
buffer.appendInt32(-428884101)
}
serializeString(emoticon, buffer: buffer, boxed: false)
break
case .inputMediaDocument(let flags, let id, let ttlSeconds, let query):
if boxed {
buffer.appendInt32(860303448)
}
serializeInt32(flags, buffer: buffer, boxed: false)
id.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeString(query!, buffer: buffer, boxed: false)}
break
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds):
if boxed {
buffer.appendInt32(-78455655)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaEmpty:
if boxed {
buffer.appendInt32(-1771768449)
}
break
case .inputMediaGame(let id):
if boxed {
buffer.appendInt32(-750828557)
}
id.serialize(buffer, true)
break
case .inputMediaGeoLive(let flags, let geoPoint, let heading, let period, let proximityNotificationRadius):
if boxed {
buffer.appendInt32(-1759532989)
}
serializeInt32(flags, buffer: buffer, boxed: false)
geoPoint.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {serializeInt32(heading!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(period!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 3) != 0 {serializeInt32(proximityNotificationRadius!, buffer: buffer, boxed: false)}
break
case .inputMediaGeoPoint(let geoPoint):
if boxed {
buffer.appendInt32(-104578748)
}
geoPoint.serialize(buffer, true)
break
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia):
if boxed {
buffer.appendInt32(-1900697899)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(title, buffer: buffer, boxed: false)
serializeString(description, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {photo!.serialize(buffer, true)}
invoice.serialize(buffer, true)
serializeBytes(payload, buffer: buffer, boxed: false)
serializeString(provider, buffer: buffer, boxed: false)
providerData.serialize(buffer, true)
if Int(flags) & Int(1 << 1) != 0 {serializeString(startParam!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 2) != 0 {extendedMedia!.serialize(buffer, true)}
break
case .inputMediaPhoto(let flags, let id, let ttlSeconds):
if boxed {
buffer.appendInt32(-1279654347)
}
serializeInt32(flags, buffer: buffer, boxed: false)
id.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds):
if boxed {
buffer.appendInt32(-440664550)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
if Int(flags) & Int(1 << 0) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaPoll(let flags, let poll, let correctAnswers, let solution, let solutionEntities):
if boxed {
buffer.appendInt32(261416433)
}
serializeInt32(flags, buffer: buffer, boxed: false)
poll.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(correctAnswers!.count))
for item in correctAnswers! {
serializeBytes(item, buffer: buffer, boxed: false)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeString(solution!, buffer: buffer, boxed: false)}
if Int(flags) & Int(1 << 1) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(solutionEntities!.count))
for item in solutionEntities! {
item.serialize(buffer, true)
}}
break
case .inputMediaStory(let peer, let id):
if boxed {
buffer.appendInt32(-1979852936)
}
peer.serialize(buffer, true)
serializeInt32(id, buffer: buffer, boxed: false)
break
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let ttlSeconds):
if boxed {
buffer.appendInt32(1530447553)
}
serializeInt32(flags, buffer: buffer, boxed: false)
file.serialize(buffer, true)
if Int(flags) & Int(1 << 2) != 0 {thumb!.serialize(buffer, true)}
serializeString(mimeType, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(attributes.count))
for item in attributes {
item.serialize(buffer, true)
}
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(stickers!.count))
for item in stickers! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
if boxed {
buffer.appendInt32(505969924)
}
serializeInt32(flags, buffer: buffer, boxed: false)
file.serialize(buffer, true)
if Int(flags) & Int(1 << 0) != 0 {buffer.appendInt32(481674261)
buffer.appendInt32(Int32(stickers!.count))
for item in stickers! {
item.serialize(buffer, true)
}}
if Int(flags) & Int(1 << 1) != 0 {serializeInt32(ttlSeconds!, buffer: buffer, boxed: false)}
break
case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType):
if boxed {
buffer.appendInt32(-1052959727)
}
geoPoint.serialize(buffer, true)
serializeString(title, buffer: buffer, boxed: false)
serializeString(address, buffer: buffer, boxed: false)
serializeString(provider, buffer: buffer, boxed: false)
serializeString(venueId, buffer: buffer, boxed: false)
serializeString(venueType, buffer: buffer, boxed: false)
break
case .inputMediaWebPage(let flags, let url):
if boxed {
buffer.appendInt32(-1038383031)
}
serializeInt32(flags, buffer: buffer, boxed: false)
serializeString(url, buffer: buffer, boxed: false)
break
}
}
public func descriptionFields() -> (String, [(String, Any)]) {
switch self {
case .inputMediaContact(let phoneNumber, let firstName, let lastName, let vcard):
return ("inputMediaContact", [("phoneNumber", phoneNumber as Any), ("firstName", firstName as Any), ("lastName", lastName as Any), ("vcard", vcard as Any)])
case .inputMediaDice(let emoticon):
return ("inputMediaDice", [("emoticon", emoticon as Any)])
case .inputMediaDocument(let flags, let id, let ttlSeconds, let query):
return ("inputMediaDocument", [("flags", flags as Any), ("id", id as Any), ("ttlSeconds", ttlSeconds as Any), ("query", query as Any)])
case .inputMediaDocumentExternal(let flags, let url, let ttlSeconds):
return ("inputMediaDocumentExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaEmpty:
return ("inputMediaEmpty", [])
case .inputMediaGame(let id):
return ("inputMediaGame", [("id", id as Any)])
case .inputMediaGeoLive(let flags, let geoPoint, let heading, let period, let proximityNotificationRadius):
return ("inputMediaGeoLive", [("flags", flags as Any), ("geoPoint", geoPoint as Any), ("heading", heading as Any), ("period", period as Any), ("proximityNotificationRadius", proximityNotificationRadius as Any)])
case .inputMediaGeoPoint(let geoPoint):
return ("inputMediaGeoPoint", [("geoPoint", geoPoint as Any)])
case .inputMediaInvoice(let flags, let title, let description, let photo, let invoice, let payload, let provider, let providerData, let startParam, let extendedMedia):
return ("inputMediaInvoice", [("flags", flags as Any), ("title", title as Any), ("description", description as Any), ("photo", photo as Any), ("invoice", invoice as Any), ("payload", payload as Any), ("provider", provider as Any), ("providerData", providerData as Any), ("startParam", startParam as Any), ("extendedMedia", extendedMedia as Any)])
case .inputMediaPhoto(let flags, let id, let ttlSeconds):
return ("inputMediaPhoto", [("flags", flags as Any), ("id", id as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaPhotoExternal(let flags, let url, let ttlSeconds):
return ("inputMediaPhotoExternal", [("flags", flags as Any), ("url", url as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaPoll(let flags, let poll, let correctAnswers, let solution, let solutionEntities):
return ("inputMediaPoll", [("flags", flags as Any), ("poll", poll as Any), ("correctAnswers", correctAnswers as Any), ("solution", solution as Any), ("solutionEntities", solutionEntities as Any)])
case .inputMediaStory(let peer, let id):
return ("inputMediaStory", [("peer", peer as Any), ("id", id as Any)])
case .inputMediaUploadedDocument(let flags, let file, let thumb, let mimeType, let attributes, let stickers, let ttlSeconds):
return ("inputMediaUploadedDocument", [("flags", flags as Any), ("file", file as Any), ("thumb", thumb as Any), ("mimeType", mimeType as Any), ("attributes", attributes as Any), ("stickers", stickers as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaUploadedPhoto(let flags, let file, let stickers, let ttlSeconds):
return ("inputMediaUploadedPhoto", [("flags", flags as Any), ("file", file as Any), ("stickers", stickers as Any), ("ttlSeconds", ttlSeconds as Any)])
case .inputMediaVenue(let geoPoint, let title, let address, let provider, let venueId, let venueType):
return ("inputMediaVenue", [("geoPoint", geoPoint as Any), ("title", title as Any), ("address", address as Any), ("provider", provider as Any), ("venueId", venueId as Any), ("venueType", venueType as Any)])
case .inputMediaWebPage(let flags, let url):
return ("inputMediaWebPage", [("flags", flags as Any), ("url", url as Any)])
}
}
public static func parse_inputMediaContact(_ reader: BufferReader) -> InputMedia? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
_4 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputMedia.inputMediaContact(phoneNumber: _1!, firstName: _2!, lastName: _3!, vcard: _4!)
}
else {
return nil
}
}
public static func parse_inputMediaDice(_ reader: BufferReader) -> InputMedia? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputMedia.inputMediaDice(emoticon: _1!)
}
else {
return nil
}
}
public static func parse_inputMediaDocument(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputDocument?
public static func parse_inputInvoiceStars(_ reader: BufferReader) -> InputInvoice? {
var _1: Api.StarsTopupOption?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputDocument
}
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputMedia.inputMediaDocument(flags: _1!, id: _2!, ttlSeconds: _3, query: _4)
}
else {
return nil
}
}
public static func parse_inputMediaDocumentExternal(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputMedia.inputMediaDocumentExternal(flags: _1!, url: _2!, ttlSeconds: _3)
}
else {
return nil
}
}
public static func parse_inputMediaEmpty(_ reader: BufferReader) -> InputMedia? {
return Api.InputMedia.inputMediaEmpty
}
public static func parse_inputMediaGame(_ reader: BufferReader) -> InputMedia? {
var _1: Api.InputGame?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputGame
_1 = Api.parse(reader, signature: signature) as? Api.StarsTopupOption
}
let _c1 = _1 != nil
if _c1 {
return Api.InputMedia.inputMediaGame(id: _1!)
}
else {
return nil
}
}
public static func parse_inputMediaGeoLive(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputGeoPoint?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
}
var _3: Int32?
if Int(_1!) & Int(1 << 2) != 0 {_3 = reader.readInt32() }
var _4: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
var _5: Int32?
if Int(_1!) & Int(1 << 3) != 0 {_5 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 3) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.InputMedia.inputMediaGeoLive(flags: _1!, geoPoint: _2!, heading: _3, period: _4, proximityNotificationRadius: _5)
}
else {
return nil
}
}
public static func parse_inputMediaGeoPoint(_ reader: BufferReader) -> InputMedia? {
var _1: Api.InputGeoPoint?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
}
let _c1 = _1 != nil
if _c1 {
return Api.InputMedia.inputMediaGeoPoint(geoPoint: _1!)
}
else {
return nil
}
}
public static func parse_inputMediaInvoice(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: Api.InputWebDocument?
if Int(_1!) & Int(1 << 0) != 0 {if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.InputWebDocument
} }
var _5: Api.Invoice?
if let signature = reader.readInt32() {
_5 = Api.parse(reader, signature: signature) as? Api.Invoice
}
var _6: Buffer?
_6 = parseBytes(reader)
var _7: String?
_7 = parseString(reader)
var _8: Api.DataJSON?
if let signature = reader.readInt32() {
_8 = Api.parse(reader, signature: signature) as? Api.DataJSON
}
var _9: String?
if Int(_1!) & Int(1 << 1) != 0 {_9 = parseString(reader) }
var _10: Api.InputMedia?
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
_10 = Api.parse(reader, signature: signature) as? Api.InputMedia
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = (Int(_1!) & Int(1 << 0) == 0) || _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
let _c7 = _7 != nil
let _c8 = _8 != nil
let _c9 = (Int(_1!) & Int(1 << 1) == 0) || _9 != nil
let _c10 = (Int(_1!) & Int(1 << 2) == 0) || _10 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 {
return Api.InputMedia.inputMediaInvoice(flags: _1!, title: _2!, description: _3!, photo: _4, invoice: _5!, payload: _6!, provider: _7!, providerData: _8!, startParam: _9, extendedMedia: _10)
}
else {
return nil
}
}
public static func parse_inputMediaPhoto(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputPhoto?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputPhoto
}
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputMedia.inputMediaPhoto(flags: _1!, id: _2!, ttlSeconds: _3)
}
else {
return nil
}
}
public static func parse_inputMediaPhotoExternal(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
var _3: Int32?
if Int(_1!) & Int(1 << 0) != 0 {_3 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputMedia.inputMediaPhotoExternal(flags: _1!, url: _2!, ttlSeconds: _3)
}
else {
return nil
}
}
public static func parse_inputMediaPoll(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.Poll?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.Poll
}
var _3: [Buffer]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: -1255641564, elementType: Buffer.self)
} }
var _4: String?
if Int(_1!) & Int(1 << 1) != 0 {_4 = parseString(reader) }
var _5: [Api.MessageEntity]?
if Int(_1!) & Int(1 << 1) != 0 {if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.MessageEntity.self)
} }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
let _c5 = (Int(_1!) & Int(1 << 1) == 0) || _5 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 {
return Api.InputMedia.inputMediaPoll(flags: _1!, poll: _2!, correctAnswers: _3, solution: _4, solutionEntities: _5)
}
else {
return nil
}
}
public static func parse_inputMediaStory(_ reader: BufferReader) -> InputMedia? {
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.InputMedia.inputMediaStory(peer: _1!, id: _2!)
}
else {
return nil
}
}
public static func parse_inputMediaUploadedDocument(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputFile?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputFile
}
var _3: Api.InputFile?
if Int(_1!) & Int(1 << 2) != 0 {if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.InputFile
} }
var _4: String?
_4 = parseString(reader)
var _5: [Api.DocumentAttribute]?
if let _ = reader.readInt32() {
_5 = Api.parseVector(reader, elementSignature: 0, elementType: Api.DocumentAttribute.self)
}
var _6: [Api.InputDocument]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_6 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputDocument.self)
} }
var _7: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_7 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 2) == 0) || _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = (Int(_1!) & Int(1 << 0) == 0) || _6 != nil
let _c7 = (Int(_1!) & Int(1 << 1) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.InputMedia.inputMediaUploadedDocument(flags: _1!, file: _2!, thumb: _3, mimeType: _4!, attributes: _5!, stickers: _6, ttlSeconds: _7)
}
else {
return nil
}
}
public static func parse_inputMediaUploadedPhoto(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.InputFile?
if let signature = reader.readInt32() {
_2 = Api.parse(reader, signature: signature) as? Api.InputFile
}
var _3: [Api.InputDocument]?
if Int(_1!) & Int(1 << 0) != 0 {if let _ = reader.readInt32() {
_3 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputDocument.self)
} }
var _4: Int32?
if Int(_1!) & Int(1 << 1) != 0 {_4 = reader.readInt32() }
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = (Int(_1!) & Int(1 << 0) == 0) || _3 != nil
let _c4 = (Int(_1!) & Int(1 << 1) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputMedia.inputMediaUploadedPhoto(flags: _1!, file: _2!, stickers: _3, ttlSeconds: _4)
}
else {
return nil
}
}
public static func parse_inputMediaVenue(_ reader: BufferReader) -> InputMedia? {
var _1: Api.InputGeoPoint?
if let signature = reader.readInt32() {
_1 = Api.parse(reader, signature: signature) as? Api.InputGeoPoint
}
var _2: String?
_2 = parseString(reader)
var _3: String?
_3 = parseString(reader)
var _4: String?
_4 = parseString(reader)
var _5: String?
_5 = parseString(reader)
var _6: String?
_6 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
let _c4 = _4 != nil
let _c5 = _5 != nil
let _c6 = _6 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 {
return Api.InputMedia.inputMediaVenue(geoPoint: _1!, title: _2!, address: _3!, provider: _4!, venueId: _5!, venueType: _6!)
}
else {
return nil
}
}
public static func parse_inputMediaWebPage(_ reader: BufferReader) -> InputMedia? {
var _1: Int32?
_1 = reader.readInt32()
var _2: String?
_2 = parseString(reader)
let _c1 = _1 != nil
let _c2 = _2 != nil
if _c1 && _c2 {
return Api.InputMedia.inputMediaWebPage(flags: _1!, url: _2!)
return Api.InputInvoice.inputInvoiceStars(option: _1!)
}
else {
return nil

View File

@ -128,7 +128,7 @@ enum AccountStateMutationOperation {
case UpdateStorySentReaction(peerId: PeerId, id: Int32, reaction: Api.Reaction)
case UpdateNewAuthorization(isUnconfirmed: Bool, hash: Int64, date: Int32, device: String, location: String)
case UpdateWallpaper(peerId: PeerId, wallpaper: TelegramWallpaper?)
case UpdateRevenueBalances(RevenueStats.Balances)
case UpdateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances)
}
struct HoleFromPreviousState {
@ -674,8 +674,8 @@ struct AccountMutableState {
self.addOperation(.UpdateNewAuthorization(isUnconfirmed: isUnconfirmed, hash: hash, date: date, device: device, location: location))
}
mutating func updateRevenueBalances(_ balances: RevenueStats.Balances) {
self.addOperation(.UpdateRevenueBalances(balances))
mutating func updateRevenueBalances(peerId: PeerId, balances: RevenueStats.Balances) {
self.addOperation(.UpdateRevenueBalances(peerId: peerId, balances: balances))
}
mutating func addOperation(_ operation: AccountStateMutationOperation) {
@ -824,7 +824,7 @@ struct AccountReplayedFinalState {
let updatedOutgoingThreadReadStates: [MessageId: MessageId.Id]
let updateConfig: Bool
let isPremiumUpdated: Bool
let updatedRevenueBalances: RevenueStats.Balances?
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
}
struct AccountFinalStateEvents {
@ -851,13 +851,13 @@ struct AccountFinalStateEvents {
let updatedOutgoingThreadReadStates: [MessageId: MessageId.Id]
let updateConfig: Bool
let isPremiumUpdated: Bool
let updatedRevenueBalances: RevenueStats.Balances?
let updatedRevenueBalances: [PeerId: RevenueStats.Balances]
var isEmpty: Bool {
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedRevenueBalances == nil
return self.addedIncomingMessageIds.isEmpty && self.addedReactionEvents.isEmpty && self.wasScheduledMessageIds.isEmpty && self.deletedMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedGroupCallParticipants.isEmpty && self.storyUpdates.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && self.dismissBotWebViews.isEmpty && self.delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated && self.updatedIncomingThreadReadStates.isEmpty && self.updatedOutgoingThreadReadStates.isEmpty && !self.updateConfig && !self.isPremiumUpdated && self.updatedRevenueBalances.isEmpty
}
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: RevenueStats.Balances? = nil) {
init(addedIncomingMessageIds: [MessageId] = [], addedReactionEvents: [(reactionAuthor: Peer, reaction: MessageReaction.Reaction, message: Message, timestamp: Int32)] = [], wasScheduledMessageIds: [MessageId] = [], deletedMessageIds: [DeletedMessageId] = [], updatedTypingActivities: [PeerActivitySpace: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedGroupCallParticipants: [(Int64, GroupCallParticipantsContext.Update)] = [], storyUpdates: [InternalStoryUpdate] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], dismissBotWebViews: [Int64] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false, updatedIncomingThreadReadStates: [MessageId: MessageId.Id] = [:], updatedOutgoingThreadReadStates: [MessageId: MessageId.Id] = [:], updateConfig: Bool = false, isPremiumUpdated: Bool = false, updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:]) {
self.addedIncomingMessageIds = addedIncomingMessageIds
self.addedReactionEvents = addedReactionEvents
self.wasScheduledMessageIds = wasScheduledMessageIds
@ -938,6 +938,6 @@ struct AccountFinalStateEvents {
let isPremiumUpdated = self.isPremiumUpdated || other.isPremiumUpdated
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, addedReactionEvents: self.addedReactionEvents + other.addedReactionEvents, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, deletedMessageIds: self.deletedMessageIds + other.deletedMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, updatedGroupCallParticipants: self.updatedGroupCallParticipants + other.updatedGroupCallParticipants, storyUpdates: self.storyUpdates + other.storyUpdates, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, dismissBotWebViews: self.dismissBotWebViews + other.dismissBotWebViews, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, updatedIncomingThreadReadStates: self.updatedIncomingThreadReadStates.merging(other.updatedIncomingThreadReadStates, uniquingKeysWith: { lhs, _ in lhs }), updateConfig: updateConfig, isPremiumUpdated: isPremiumUpdated, updatedRevenueBalances: self.updatedRevenueBalances != nil ? self.updatedRevenueBalances : other.updatedRevenueBalances)
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, addedReactionEvents: self.addedReactionEvents + other.addedReactionEvents, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, deletedMessageIds: self.deletedMessageIds + other.deletedMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, updatedGroupCallParticipants: self.updatedGroupCallParticipants + other.updatedGroupCallParticipants, storyUpdates: self.storyUpdates + other.storyUpdates, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, dismissBotWebViews: self.dismissBotWebViews + other.dismissBotWebViews, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated, updatedIncomingThreadReadStates: self.updatedIncomingThreadReadStates.merging(other.updatedIncomingThreadReadStates, uniquingKeysWith: { lhs, _ in lhs }), updateConfig: updateConfig, isPremiumUpdated: isPremiumUpdated, updatedRevenueBalances: self.updatedRevenueBalances.merging(other.updatedRevenueBalances, uniquingKeysWith: { lhs, _ in lhs }))
}
}

View File

@ -1776,8 +1776,8 @@ private func finalStateWithUpdatesAndServerTime(accountPeerId: PeerId, postbox:
updatedState.updateNewAuthorization(isUnconfirmed: isUnconfirmed, hash: hash, date: date ?? 0, device: device ?? "", location: location ?? "")
case let .updatePeerWallpaper(_, peer, wallpaper):
updatedState.updateWallpaper(peerId: peer.peerId, wallpaper: wallpaper.flatMap { TelegramWallpaper(apiWallpaper: $0) })
case let .updateBroadcastRevenueTransactions(_, balances):
updatedState.updateRevenueBalances(RevenueStats.Balances(apiRevenueBalances: balances))
case let .updateBroadcastRevenueTransactions(peer, balances):
updatedState.updateRevenueBalances(peerId: peer.peerId, balances: RevenueStats.Balances(apiRevenueBalances: balances))
default:
break
}
@ -3402,7 +3402,7 @@ func replayFinalState(
var deletedMessageIds: [DeletedMessageId] = []
var syncAttachMenuBots = false
var updateConfig = false
var updatedRevenueBalances: RevenueStats.Balances?
var updatedRevenueBalances: [PeerId: RevenueStats.Balances] = [:]
var holesFromPreviousStateMessageIds: [MessageId] = []
var clearHolesFromPreviousStateForChannelMessagesWithPts: [PeerIdAndMessageNamespace: Int32] = [:]
@ -4828,8 +4828,8 @@ func replayFinalState(
} else {
transaction.removeOrderedItemListItem(collectionId: Namespaces.OrderedItemList.NewSessionReviews, itemId: id.rawValue)
}
case let .UpdateRevenueBalances(balances):
updatedRevenueBalances = balances
case let .UpdateRevenueBalances(peerId, balances):
updatedRevenueBalances[peerId] = balances
}
}

View File

@ -45,7 +45,7 @@ private final class UpdatedPeersNearbySubscriberContext {
}
private final class UpdatedRevenueBalancesSubscriberContext {
let subscribers = Bag<(RevenueStats.Balances) -> Void>()
let subscribers = Bag<([PeerId: RevenueStats.Balances]) -> Void>()
}
public enum DeletedMessageId: Hashable {
@ -1027,8 +1027,8 @@ public final class AccountStateManager {
if let updatedPeersNearby = events.updatedPeersNearby {
strongSelf.notifyUpdatedPeersNearby(updatedPeersNearby)
}
if let updatedRevenueBalances = events.updatedRevenueBalances {
strongSelf.notifyUpdatedRevenueBalances(updatedRevenueBalances)
if !events.updatedRevenueBalances.isEmpty {
strongSelf.notifyUpdatedRevenueBalances(events.updatedRevenueBalances)
}
if !events.updatedCalls.isEmpty {
for call in events.updatedCalls {
@ -1602,7 +1602,7 @@ public final class AccountStateManager {
}
}
public func updatedRevenueBalances() -> Signal<RevenueStats.Balances, NoError> {
public func updatedRevenueBalances() -> Signal<[PeerId: RevenueStats.Balances], NoError> {
let queue = self.queue
return Signal { [weak self] subscriber in
let disposable = MetaDisposable()
@ -1623,7 +1623,7 @@ public final class AccountStateManager {
}
}
private func notifyUpdatedRevenueBalances(_ updatedRevenueBalances: RevenueStats.Balances) {
private func notifyUpdatedRevenueBalances(_ updatedRevenueBalances: [PeerId: RevenueStats.Balances]) {
for subscriber in self.updatedRevenueBalancesContext.subscribers.copyItems() {
subscriber(updatedRevenueBalances)
}
@ -1916,7 +1916,7 @@ public final class AccountStateManager {
}
}
public func updatedRevenueBalances() -> Signal<RevenueStats.Balances, NoError> {
public func updatedRevenueBalances() -> Signal<[PeerId: RevenueStats.Balances], NoError> {
return self.impl.signalWith { impl, subscriber in
return impl.updatedRevenueBalances().start(next: subscriber.putNext, error: subscriber.putError, completed: subscriber.putCompletion)
}

View File

@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
public class Serialization: NSObject, MTSerialization {
public func currentLayer() -> UInt {
return 180
return 181
}
public func parseMessage(_ data: Data!) -> Any! {

View File

@ -135,6 +135,7 @@ private final class RevenueStatsContextImpl {
assert(Queue.mainQueue().isCurrent())
let account = self.account
let peerId = self.peerId
let signal = requestRevenueStats(postbox: self.account.postbox, network: self.account.network, peerId: self.peerId)
|> mapToSignal { initial -> Signal<RevenueStats?, NoError> in
guard let initial else {
@ -143,8 +144,11 @@ private final class RevenueStatsContextImpl {
return .single(initial)
|> then(
account.stateManager.updatedRevenueBalances()
|> map { balances in
return initial.withUpdated(balances: balances)
|> mapToSignal { updates in
if let balances = updates[peerId] {
return .single(initial.withUpdated(balances: balances))
}
return .complete()
}
)
}

View File

@ -17,6 +17,7 @@ public enum AppStoreTransactionPurpose {
case gift(peerId: EnginePeer.Id, currency: String, amount: Int64)
case giftCode(peerIds: [EnginePeer.Id], boostPeer: EnginePeer.Id?, currency: String, amount: Int64)
case giveaway(boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64)
case stars(count: Int64, currency: String, amount: Int64)
}
private func apiInputStorePaymentPurpose(account: Account, purpose: AppStoreTransactionPurpose) -> Signal<Api.InputStorePaymentPurpose, NoError> {
@ -89,6 +90,8 @@ private func apiInputStorePaymentPurpose(account: Account, purpose: AppStoreTran
return .single(.inputStorePaymentPremiumGiveaway(flags: flags, boostPeer: apiBoostPeer, additionalPeers: additionalPeers, countriesIso2: countries, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate, currency: currency, amount: amount))
}
|> switchToLatest
case let .stars(count, currency, amount):
return .single(.inputStorePaymentStars(flags: 0, stars: count, currency: currency, amount: amount))
}
}

View File

@ -9,9 +9,9 @@ public enum BotPaymentInvoiceSource {
case slug(String)
case premiumGiveaway(boostPeer: EnginePeer.Id, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32, currency: String, amount: Int64, option: PremiumGiftCodeOption)
case giftCode(users: [PeerId], currency: String, amount: Int64, option: PremiumGiftCodeOption)
case stars(option: StarsTopUpOption)
}
public struct BotPaymentInvoiceFields: OptionSet {
public var rawValue: Int32
@ -257,8 +257,6 @@ private func _internal_parseInputInvoice(transaction: Transaction, source: BotPa
return .inputInvoicePremiumGiftCode(purpose: inputPurpose, option: option)
case let .giftCode(users, currency, amount, option):
var inputUsers: [Api.InputUser] = []
if !users.isEmpty {
for peerId in users {
@ -269,7 +267,6 @@ private func _internal_parseInputInvoice(transaction: Transaction, source: BotPa
}
let inputPurpose: Api.InputStorePaymentPurpose = .inputStorePaymentPremiumGiftCode(flags: 0, users: inputUsers, boostPeer: nil, currency: currency, amount: amount)
var flags: Int32 = 0
if let _ = option.storeProductId {
@ -282,7 +279,14 @@ private func _internal_parseInputInvoice(transaction: Transaction, source: BotPa
let option: Api.PremiumGiftCodeOption = .premiumGiftCodeOption(flags: flags, users: option.users, months: option.months, storeProduct: option.storeProductId, storeQuantity: option.storeQuantity, currency: option.currency, amount: option.amount)
return .inputInvoicePremiumGiftCode(purpose: inputPurpose, option: option)
case let .stars(option):
var flags: Int32 = 0
if let _ = option.storeProductId {
flags |= (1 << 0)
}
return .inputInvoiceStars(
option: .starsTopupOption(flags: flags, stars: option.count, storeProduct: option.storeProductId, currency: option.currency, amount: option.amount)
)
}
}
@ -569,6 +573,8 @@ func _internal_sendBotPaymentForm(account: Account, formId: Int64, source: BotPa
}
case .giftCode:
receiptMessageId = nil
case .stars:
receiptMessageId = nil
}
}
}

View File

@ -31,6 +31,7 @@ public struct PremiumGiftCodeOption: Codable, Equatable {
public let storeQuantity: Int32
public let currency: String
public let amount: Int64
public init(users: Int32, months: Int32, storeProductId: String?, storeQuantity: Int32, currency: String, amount: Int64) {
self.users = users
self.months = months

View File

@ -0,0 +1,247 @@
import Foundation
import Postbox
import MtProtoKit
import SwiftSignalKit
import TelegramApi
public struct StarsTopUpOption: Codable, Equatable {
enum CodingKeys: String, CodingKey {
case count
case storeProductId
case currency
case amount
}
public let count: Int64
public let storeProductId: String?
public let currency: String
public let amount: Int64
public init(count: Int64, storeProductId: String?, currency: String, amount: Int64) {
self.count = count
self.storeProductId = storeProductId
self.currency = currency
self.amount = amount
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.count = try container.decode(Int64.self, forKey: .count)
self.storeProductId = try container.decodeIfPresent(String.self, forKey: .storeProductId)
self.currency = try container.decode(String.self, forKey: .currency)
self.amount = try container.decode(Int64.self, forKey: .amount)
}
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.count, forKey: .count)
try container.encodeIfPresent(self.storeProductId, forKey: .storeProductId)
try container.encode(self.currency, forKey: .currency)
try container.encode(self.amount, forKey: .amount)
}
}
extension StarsTopUpOption {
init(apiStarsTopupOption: Api.StarsTopupOption) {
switch apiStarsTopupOption {
case let .starsTopupOption(_, stars, storeProduct, currency, amount):
self.init(count: stars, storeProductId: storeProduct, currency: currency, amount: amount)
}
}
}
func _internal_starsTopUpOptions(account: Account) -> Signal<[StarsTopUpOption], NoError> {
return account.network.request(Api.functions.payments.getStarsTopupOptions())
|> map(Optional.init)
|> `catch` { _ -> Signal<[Api.StarsTopupOption]?, NoError> in
return .single(nil)
}
|> mapToSignal { results -> Signal<[StarsTopUpOption], NoError> in
if let results = results {
return .single(results.map { StarsTopUpOption(apiStarsTopupOption: $0) })
} else {
return .single([])
}
}
}
private struct InternalStarsStatus {
let balance: Int64
let transactions: [StarsContext.State.Transaction]
let nextOffset: String?
}
private func requestStarsState(account: Account, peerId: EnginePeer.Id, offset: String?) -> Signal<InternalStarsStatus?, NoError> {
return account.postbox.transaction { transaction -> Peer? in
return transaction.getPeer(peerId)
} |> mapToSignal { peer -> Signal<InternalStarsStatus?, NoError> in
guard let peer, let inputPeer = apiInputPeer(peer) else {
return .never()
}
let signal: Signal<Api.payments.StarsStatus, MTRpcError>
if let offset {
signal = account.network.request(Api.functions.payments.getStarsTransactions(flags: 0, peer: inputPeer, offset: offset))
} else {
signal = account.network.request(Api.functions.payments.getStarsStatus(peer: inputPeer))
}
return signal
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.payments.StarsStatus?, NoError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<InternalStarsStatus?, NoError> in
guard let result else {
return .single(nil)
}
return account.postbox.transaction { transaction -> InternalStarsStatus? in
switch result {
case let .starsStatus(_, balance, history, nextOffset, chats, users):
let peers = AccumulatedPeers(chats: chats, users: users)
updatePeers(transaction: transaction, accountPeerId: account.peerId, peers: peers)
var parsedTransactions: [StarsContext.State.Transaction] = []
for entry in history {
switch entry {
case let .starsTransaction(id, stars, date, peer):
if let peer = transaction.getPeer(peer.peerId) {
parsedTransactions.append(StarsContext.State.Transaction(id: id, count: stars, date: date, peer: EnginePeer(peer)))
}
}
}
return InternalStarsStatus(balance: balance, transactions: parsedTransactions, nextOffset: nextOffset)
}
}
}
}
}
private final class StarsContextImpl {
private let account: Account
private let peerId: EnginePeer.Id
private var _state: StarsContext.State? {
didSet {
if self._state != oldValue {
self._statePromise.set(.single(self._state))
}
}
}
private let _statePromise = Promise<StarsContext.State?>()
var state: Signal<StarsContext.State?, NoError> {
return self._statePromise.get()
}
private var nextOffset: String?
private let disposable = MetaDisposable()
init(account: Account, peerId: EnginePeer.Id) {
assert(Queue.mainQueue().isCurrent())
self.account = account
self.peerId = peerId
self._state = nil
self._statePromise.set(.single(nil))
self.load()
}
deinit {
assert(Queue.mainQueue().isCurrent())
self.disposable.dispose()
}
func load() {
assert(Queue.mainQueue().isCurrent())
self.disposable.set((requestStarsState(account: self.account, peerId: self.peerId, offset: nil)
|> deliverOnMainQueue).start(next: { [weak self] status in
if let self {
if let status {
self._state = StarsContext.State(balance: status.balance, transactions: status.transactions)
self.nextOffset = status.nextOffset
} else {
self._state = nil
}
}
}))
}
func loadMore() {
assert(Queue.mainQueue().isCurrent())
guard let currentState = self._state, let nextOffset = self.nextOffset else {
return
}
self.disposable.set((requestStarsState(account: self.account, peerId: self.peerId, offset: nextOffset)
|> deliverOnMainQueue).start(next: { [weak self] status in
if let self {
if let status {
self._state = StarsContext.State(balance: status.balance, transactions: currentState.transactions + status.transactions)
self.nextOffset = status.nextOffset
} else {
self.nextOffset = nil
}
}
}))
}
}
public final class StarsContext {
public struct State: Equatable {
public struct Transaction: Equatable {
public let id: String
public let count: Int64
public let date: Int32
public let peer: EnginePeer
init(id: String, count: Int64, date: Int32, peer: EnginePeer) {
self.id = id
self.count = count
self.date = date
self.peer = peer
}
}
public let balance: Int64
public let transactions: [Transaction]
init(balance: Int64, transactions: [Transaction]) {
self.balance = balance
self.transactions = transactions
}
public static func == (lhs: State, rhs: State) -> Bool {
if lhs.balance != rhs.balance {
return false
}
if lhs.transactions != rhs.transactions {
return false
}
return true
}
}
private let impl: QueueLocalObject<StarsContextImpl>
public var state: Signal<StarsContext.State?, NoError> {
return Signal { subscriber in
let disposable = MetaDisposable()
self.impl.with { impl in
disposable.set(impl.state.start(next: { value in
subscriber.putNext(value)
}))
}
return disposable
}
}
init(account: Account, peerId: EnginePeer.Id) {
self.impl = QueueLocalObject(queue: Queue.mainQueue(), generate: {
return StarsContextImpl(account: account, peerId: peerId)
})
}
}

View File

@ -65,5 +65,13 @@ public extension TelegramEngine {
public func launchPrepaidGiveaway(peerId: EnginePeer.Id, id: Int64, additionalPeerIds: [EnginePeer.Id], countries: [String], onlyNewSubscribers: Bool, showWinners: Bool, prizeDescription: String?, randomId: Int64, untilDate: Int32) -> Signal<Never, LaunchPrepaidGiveawayError> {
return _internal_launchPrepaidGiveaway(account: self.account, peerId: peerId, id: id, additionalPeerIds: additionalPeerIds, countries: countries, onlyNewSubscribers: onlyNewSubscribers, showWinners: showWinners, prizeDescription: prizeDescription, randomId: randomId, untilDate: untilDate)
}
}
public func starsTopUpOptions() -> Signal<[StarsTopUpOption], NoError> {
return _internal_starsTopUpOptions(account: self.account)
}
public func peerStarsContext(peerId: EnginePeer.Id) -> StarsContext {
return StarsContext(account: self.account, peerId: peerId)
}
}
}

View File

@ -175,7 +175,7 @@ public final class ChatBotInfoItemNode: ListViewItemNode {
break
case .ignore:
return .fail
case .url, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji:
case .url, .phone, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji:
return .waitForSingleTap
}
}

View File

@ -141,6 +141,7 @@ public struct ChatMessageBubbleContentTapAction {
public enum Content {
case none
case url(Url)
case phone(String)
case textMention(String)
case peerMention(peerId: PeerId, mention: String, openProfile: Bool)
case botCommand(String)

View File

@ -770,24 +770,24 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
}
self.mainContextSourceNode.willUpdateIsExtractedToContextPreview = { [weak self] isExtractedToContextPreview, _ in
guard let strongSelf = self, let _ = strongSelf.item else {
guard let self, let _ = self.item else {
return
}
for contentNode in strongSelf.contentNodes {
for contentNode in self.contentNodes {
contentNode.willUpdateIsExtractedToContextPreview(isExtractedToContextPreview)
}
}
self.mainContextSourceNode.isExtractedToContextPreviewUpdated = { [weak self] isExtractedToContextPreview in
guard let strongSelf = self else {
guard let self else {
return
}
strongSelf.backgroundWallpaperNode.setMaskMode(strongSelf.backgroundMaskMode)
strongSelf.backgroundNode.setMaskMode(strongSelf.backgroundMaskMode)
if !isExtractedToContextPreview, let (rect, size) = strongSelf.absoluteRect {
strongSelf.updateAbsoluteRect(rect, within: size)
self.backgroundWallpaperNode.setMaskMode(self.backgroundMaskMode)
self.backgroundNode.setMaskMode(self.backgroundMaskMode)
if !isExtractedToContextPreview, let (rect, size) = self.absoluteRect {
self.updateAbsoluteRect(rect, within: size)
}
for contentNode in strongSelf.contentNodes {
for contentNode in self.contentNodes {
contentNode.updateIsExtractedToContextPreview(isExtractedToContextPreview)
}
}
@ -811,7 +811,7 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
strongSelf.applyAbsoluteOffsetSpringInternal(value: value, duration: duration, damping: damping)
}
}
required public init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@ -1150,15 +1150,15 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
let contentNodePoint = strongSelf.view.convert(point, to: contentNode.view)
let tapAction = contentNode.tapActionAtPoint(contentNodePoint, gesture: .tap, isEstimating: true)
switch tapAction.content {
case .none:
if let _ = strongSelf.item?.controllerInteraction.tapMessage {
return .waitForSingleTap
}
break
case .ignore:
return .fail
case .url, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji:
case .none:
if let _ = strongSelf.item?.controllerInteraction.tapMessage {
return .waitForSingleTap
}
break
case .ignore:
return .fail
case .url, .phone, .peerMention, .textMention, .botCommand, .hashtag, .instantPage, .wallpaper, .theme, .call, .openMessage, .timecode, .bankCard, .tooltip, .openPollResults, .copy, .largeEmoji, .customEmoji:
return .waitForSingleTap
}
}
@ -4600,6 +4600,16 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
item.controllerInteraction.openUrl(ChatControllerInteraction.OpenUrl(url: url.url, concealed: url.concealed, message: item.content.firstMessage, allowInlineWebpageResolution: url.allowInlineWebpageResolution, progress: tapAction.activate?()))
}, contextMenuOnLongPress: !tapAction.hasLongTapAction))
}
case let .phone(number):
return .action(InternalBubbleTapAction.Action({ [weak self] in
guard let self, let item = self.item, let contentNode = self.contextContentNodeForPhoneNumber(number) else {
return
}
self.addSubnode(contentNode)
item.controllerInteraction.openPhoneContextMenu(ChatControllerInteraction.OpenPhone(number: number, message: item.content.firstMessage, contentNode: contentNode, messageNode: self, progress: tapAction.activate?()))
}, contextMenuOnLongPress: !tapAction.hasLongTapAction))
case let .peerMention(peerId, _, openProfile):
return .action(InternalBubbleTapAction.Action { [weak self] in
if let item = self?.item {
@ -4762,6 +4772,16 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
} else {
disableDefaultPressAnimation = true
}
case let .phone(number):
return .action(InternalBubbleTapAction.Action({ [weak self] in
guard let self, let item = self.item, let contentNode = self.contextContentNodeForPhoneNumber(number) else {
return
}
self.addSubnode(contentNode)
item.controllerInteraction.openPhoneContextMenu(ChatControllerInteraction.OpenPhone(number: number, message: item.content.firstMessage, contentNode: contentNode, messageNode: self, progress: tapAction.activate?()))
}, contextMenuOnLongPress: !tapAction.hasLongTapAction))
case let .peerMention(peerId, mention, _):
return .action(InternalBubbleTapAction.Action {
item.controllerInteraction.longTap(.peerMention(peerId, mention), message)
@ -4829,6 +4849,39 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
return nil
}
private func contextContentNodeForPhoneNumber(_ number: String) -> ContextExtractedContentContainingNode? {
guard let item = self.item else {
return nil
}
let containingNode = ContextExtractedContentContainingNode()
let incoming = item.content.effectivelyIncoming(item.context.account.peerId, associatedData: item.associatedData)
let textNode = ImmediateTextNode()
textNode.attributedText = NSAttributedString(string: number, font: Font.regular(item.presentationData.fontSize.baseDisplaySize), textColor: incoming ? item.presentationData.theme.theme.chat.message.incoming.linkTextColor : item.presentationData.theme.theme.chat.message.outgoing.linkTextColor)
let textSize = textNode.updateLayout(CGSize(width: 1000.0, height: 100.0))
let backgroundNode = ASDisplayNode()
backgroundNode.backgroundColor = (incoming ? item.presentationData.theme.theme.chat.message.incoming.bubble.withoutWallpaper.fill : item.presentationData.theme.theme.chat.message.outgoing.bubble.withoutWallpaper.fill).first ?? .black
backgroundNode.clipsToBounds = true
backgroundNode.cornerRadius = 10.0
let insets = UIEdgeInsets(top: 5.0, left: 8.0, bottom: 5.0, right: 8.0)
let backgroundSize = CGSize(width: textSize.width + insets.left + insets.right, height: textSize.height + insets.top + insets.bottom)
backgroundNode.frame = CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: backgroundSize)
textNode.frame = CGRect(origin: CGPoint(x: insets.left, y: insets.top), size: textSize)
backgroundNode.addSubnode(textNode)
containingNode.frame = CGRect(origin: CGPoint(x: self.backgroundNode.frame.minX + 3.0, y: 1.0), size: CGSize(width: backgroundSize.width, height: backgroundSize.height + 20.0))
containingNode.contentNode.frame = CGRect(origin: .zero, size: backgroundSize)
containingNode.contentRect = CGRect(origin: .zero, size: backgroundSize)
containingNode.contentNode.addSubnode(backgroundNode)
containingNode.contentNode.alpha = 0.0
return containingNode
}
private func traceSelectionNodes(parent: ASDisplayNode, point: CGPoint) -> ASDisplayNode? {
if let parent = parent as? FileMessageSelectionNode, parent.bounds.contains(point) {
return parent

View File

@ -857,7 +857,15 @@ public class ChatMessageTextBubbleContentNode: ChatMessageBubbleContentNode {
urlRange = urlRangeValue
concealed = !doesUrlMatchText(url: url, text: attributeText, fullText: fullText)
}
return ChatMessageBubbleContentTapAction(content: .url(ChatMessageBubbleContentTapAction.Url(url: url, concealed: concealed)), activate: { [weak self] in
var content: ChatMessageBubbleContentTapAction.Content
if url.hasPrefix("tel:") {
content = .phone(url.replacingOccurrences(of: "tel:", with: ""))
} else {
content = .url(ChatMessageBubbleContentTapAction.Url(url: url, concealed: concealed))
}
return ChatMessageBubbleContentTapAction(content: content, activate: { [weak self] in
guard let self else {
return nil
}

View File

@ -613,7 +613,9 @@ final class ChatRecentActionsControllerNode: ViewControllerTracingNode {
}, openPremiumStatusInfo: { _, _, _, _ in
}, openRecommendedChannelContextMenu: { _, _, _ in
}, openGroupBoostInfo: { _, _ in
}, openStickerEditor: {
}, openStickerEditor: {
}, openPhoneContextMenu: { _ in
}, openAgeRestrictedMessageMedia: { _, _ in
}, playMessageEffect: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {

View File

@ -148,6 +148,22 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
}
}
public struct OpenPhone {
public var number: String
public var message: Message
public var contentNode: ContextExtractedContentContainingNode
public var messageNode: ASDisplayNode
public var progress: Promise<Bool>?
public init(number: String, message: Message, contentNode: ContextExtractedContentContainingNode, messageNode: ASDisplayNode, progress: Promise<Bool>? = nil) {
self.number = number
self.message = message
self.contentNode = contentNode
self.messageNode = messageNode
self.progress = progress
}
}
public let openMessage: (Message, OpenMessageParams) -> Bool
public let openPeer: (EnginePeer, ChatControllerInteractionNavigateToPeer, MessageReference?, OpenPeerSource) -> Void
public let openPeerMention: (String, Promise<Bool>?) -> Void
@ -242,6 +258,8 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
public let openRecommendedChannelContextMenu: (EnginePeer, UIView, ContextGesture?) -> Void
public let openGroupBoostInfo: (EnginePeer.Id?, Int) -> Void
public let openStickerEditor: () -> Void
public let openPhoneContextMenu: (OpenPhone) -> Void
public let openAgeRestrictedMessageMedia: (Message, @escaping () -> Void) -> Void
public let playMessageEffect: (Message) -> Void
public let requestMessageUpdate: (MessageId, Bool) -> Void
@ -368,6 +386,8 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
openRecommendedChannelContextMenu: @escaping (EnginePeer, UIView, ContextGesture?) -> Void,
openGroupBoostInfo: @escaping (EnginePeer.Id?, Int) -> Void,
openStickerEditor: @escaping () -> Void,
openPhoneContextMenu: @escaping (OpenPhone) -> Void,
openAgeRestrictedMessageMedia: @escaping (Message, @escaping () -> Void) -> Void,
playMessageEffect: @escaping (Message) -> Void,
requestMessageUpdate: @escaping (MessageId, Bool) -> Void,
cancelInteractiveKeyboardGestures: @escaping () -> Void,
@ -474,6 +494,8 @@ public final class ChatControllerInteraction: ChatControllerInteractionProtocol
self.openRecommendedChannelContextMenu = openRecommendedChannelContextMenu
self.openGroupBoostInfo = openGroupBoostInfo
self.openStickerEditor = openStickerEditor
self.openPhoneContextMenu = openPhoneContextMenu
self.openAgeRestrictedMessageMedia = openAgeRestrictedMessageMedia
self.playMessageEffect = playMessageEffect
self.requestMessageUpdate = requestMessageUpdate

View File

@ -3325,7 +3325,9 @@ final class PeerInfoScreenNode: ViewControllerTracingNode, PeerInfoScreenNodePro
}, openPremiumStatusInfo: { _, _, _, _ in
}, openRecommendedChannelContextMenu: { _, _, _ in
}, openGroupBoostInfo: { _, _ in
}, openStickerEditor: {
}, openStickerEditor: {
}, openPhoneContextMenu: { _ in
}, openAgeRestrictedMessageMedia: { _, _ in
}, playMessageEffect: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {

View File

@ -493,19 +493,13 @@ public class ShareRootControllerImpl {
let displayShare: () -> Void = {
var cancelImpl: (() -> Void)?
let _ = cancelImpl
let beginShare: () -> Void = {
let requestUserInteraction: ([UnpreparedShareItemContent]) -> Signal<[PreparedShareItemContent], NoError> = { content in
return Signal { [weak self] subscriber in
switch content[0] {
case let .contact(data):
#if !DEBUG
//qwefqwfqwefw
#endif
let _ = data
let _ = self
/*let controller = deviceContactInfoController(context: context, subject: .filter(peer: nil, contactId: nil, contactData: data, completion: { peer, contactData in
let controller = deviceContactInfoController(context: context, environment: environment, subject: .filter(peer: nil, contactId: nil, contactData: data, completion: { peer, contactData in
let phone = contactData.basicData.phoneNumbers[0].value
if let vCardData = contactData.serializedVCard() {
subscriber.putNext([.media(.media(.standalone(media: TelegramMediaContact(firstName: contactData.basicData.firstName, lastName: contactData.basicData.lastName, phoneNumber: phone, peerId: nil, vCardData: vCardData))))])
@ -518,7 +512,7 @@ public class ShareRootControllerImpl {
if let strongSelf = self, let window = strongSelf.mainWindow {
controller.presentationArguments = ViewControllerPresentationArguments(presentationAnimation: .modalSheet)
window.present(controller, on: .root)
}*/
}
break
}
return EmptyDisposable

View File

@ -1762,7 +1762,7 @@ final class StoryItemSetContainerSendMessage {
self.sendMessages(view: view, peer: targetPeer, messages: enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime)
} else {
let contactController = component.context.sharedContext.makeDeviceContactInfoController(context: component.context, subject: .filter(peer: peerAndContactData.0?._asPeer(), contactId: nil, contactData: contactData, completion: { [weak self, weak view] peer, contactData in
let contactController = component.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: component.context), environment: ShareControllerAppEnvironment(sharedContext: component.context.sharedContext), subject: .filter(peer: peerAndContactData.0?._asPeer(), contactId: nil, contactData: contactData, completion: { [weak self, weak view] peer, contactData in
guard let self, let view else {
return
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,143 @@
%PDF-1.7
1 0 obj
<< /Filter /FlateDecode
/Type /XObject
/Length 2 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 24.000000 24.000000 ]
>>
stream
xm•Í®E …÷ý½F¢R¶Ë.×<16>X<03>0
é&ŠÄóçs§§§ós7S÷Œ<C592><7F>=ï~{ÿÿ¿<C3BF>÷þþËþë_Û»×<C397>´~üíýùøùz]ßY±Ôrmtµ1öLJí2ûþñéñÀ™ÃÄwm¹¨ôý`äên»x“c*Ilê˜d»A2§ö¼¹>H·RÖˆ§û“|/hز ÙÍUÇ<55>®¸Vä/ho°j•ªà,ïñYm\®ÄÖçòYñžyoÐYÝÝõêBŒ¬kЧî)g)ÝWˆÀ¯çhtÙwokyï« ìêš{´%@^ñf“è±rŸÄšP 4"ø:yøÐQ®3,˜´v¸Ò­k'žôJ†å.ÚVg¸[<5B>äË zl“QÛ ·H¸‰'®ÚÒdRSµ3R±Ò¦«Ï.¸þ@oÛ?›·¹¬;­#;ŠŽD/ÙÌ^PĘALyFæš`<60>‡UŸg…Ù¥Èâq"ëKuFÞF|"9zsff1@LJ!+3"•Â
À<EFBFBD><EFBFBD>µ„è/ä±­–Bˆ ƒg
fD¡jR\Ðl^VEîÄ(R<>U&£cøS9÷b×X·€\QúÀUÚ¢(-ƒ] ƒ}Ÿ64jF"¬ˆæ¡s¢¯ º—r<E28094>¤ë:éðZÑ'ÄW¶²¼ðJ$c9R¸<52>dc(p
F7¨þÁàè<>}[,m<>þ”l<E2809D>œW/š- U±±±jQYEéE7Òä´ôtZ{lƒÆQb ƒu<72>Ö¼Ñ;wm™T5t ¬Æ…Ü8¹0ÎJLgGYV˜¶:”‡ÜJ"'R t¥œ C ƒ£QWA<57>õ  ·¥ÌÏèì<C3A8>"C ËÁ5Xôæ“ÕwªÇéÚr@4;´äVsyÒ}–Áî>*¿Ž T\<ù“†4i¨.«z&n§¦~Ö2pqžšÒÕjáÎSƒç7c«aB<61>-zÀ5{@:ÃDµsvw0)tDƒaÉ'_u-<2D>K†¤b#9µ<E280BA>\}áHS­­:Òu(–û\…X¤Ï¨Š!U—…\”͉”BµsëÊžXUŠUí…N<4A>nXDvÄVˆÕ]§A…|Ýs1ñ÷OÛÇí<C387>í3Ü
endstream
endobj
2 0 obj
868
endobj
3 0 obj
<< /Type /XObject
/Length 4 0 R
/Group << /Type /Group
/S /Transparency
>>
/Subtype /Form
/Resources << >>
/BBox [ 0.000000 0.000000 24.000000 24.000000 ]
>>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 0.000000 0.000000 cm
0.000000 0.000000 0.000000 scn
0.000000 12.800001 m
0.000000 16.720367 0.000000 18.680552 0.762954 20.177933 c
1.434068 21.495068 2.504932 22.565931 3.822066 23.237045 c
5.319448 24.000000 7.279633 24.000000 11.200000 24.000000 c
12.800001 24.000000 l
16.720367 24.000000 18.680552 24.000000 20.177933 23.237045 c
21.495068 22.565931 22.565931 21.495068 23.237045 20.177933 c
24.000000 18.680552 24.000000 16.720367 24.000000 12.800000 c
24.000000 11.199999 l
24.000000 7.279633 24.000000 5.319448 23.237045 3.822067 c
22.565931 2.504932 21.495068 1.434069 20.177933 0.762955 c
18.680552 0.000000 16.720367 0.000000 12.800000 0.000000 c
11.199999 0.000000 l
7.279632 0.000000 5.319448 0.000000 3.822066 0.762955 c
2.504932 1.434069 1.434068 2.504932 0.762954 3.822067 c
0.000000 5.319448 0.000000 7.279633 0.000000 11.200000 c
0.000000 12.800001 l
h
f
n
Q
endstream
endobj
4 0 obj
944
endobj
5 0 obj
<< /XObject << /X1 1 0 R >>
/ExtGState << /E1 << /SMask << /Type /Mask
/G 3 0 R
/S /Alpha
>>
/Type /ExtGState
>> >>
>>
endobj
6 0 obj
<< /Length 7 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
/E1 gs
/X1 Do
Q
endstream
endobj
7 0 obj
46
endobj
8 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 5 0 R
/Contents 6 0 R
/Parent 9 0 R
>>
endobj
9 0 obj
<< /Kids [ 8 0 R ]
/Count 1
/Type /Pages
>>
endobj
10 0 obj
<< /Pages 9 0 R
/Type /Catalog
>>
endobj
xref
0 11
0000000000 65535 f
0000000010 00000 n
0000001152 00000 n
0000001174 00000 n
0000002366 00000 n
0000002388 00000 n
0000002686 00000 n
0000002788 00000 n
0000002809 00000 n
0000002982 00000 n
0000003056 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 10 0 R
/Size 11
>>
startxref
3116
%%EOF

View File

@ -1,9 +1,9 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
"author" : "xcode",
"version" : 1
},
"properties" : {
"provides-namespace" : true
}
}
}

View File

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

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

View File

@ -0,0 +1,241 @@
import Foundation
import UIKit
import SwiftSignalKit
import Postbox
import TelegramCore
import AsyncDisplayKit
import Display
import TelegramNotices
import ContextUI
import AccountContext
import ChatMessageItemView
import ChatMessageItemCommon
import AvatarNode
import UndoUI
import MessageUI
import PeerInfoUI
extension ChatControllerImpl: MFMessageComposeViewControllerDelegate {
func openPhoneContextMenu(number: String, peer: EnginePeer?, message: Message, contentNode: ContextExtractedContentContainingNode, messageNode: ASDisplayNode, frame: CGRect, anyRecognizer: UIGestureRecognizer?, location: CGPoint?) -> Void {
if self.presentationInterfaceState.interfaceState.selectionState != nil {
return
}
self.dismissAllTooltips()
let recognizer: TapLongTapOrDoubleTapGestureRecognizer? = anyRecognizer as? TapLongTapOrDoubleTapGestureRecognizer
let gesture: ContextGesture? = anyRecognizer as? ContextGesture
if let messages = self.chatDisplayNode.historyNode.messageGroupInCurrentHistoryView(message.id) {
(self.view.window as? WindowHost)?.cancelInteractiveKeyboardGestures()
self.chatDisplayNode.cancelInteractiveKeyboardGestures()
var updatedMessages = messages
for i in 0 ..< updatedMessages.count {
if updatedMessages[i].id == message.id {
let message = updatedMessages.remove(at: i)
updatedMessages.insert(message, at: 0)
break
}
}
self.chatDisplayNode.messageTransitionNode.dismissMessageReactionContexts()
let source: ContextContentSource
if let location = location {
source = .location(ChatMessageContextLocationContentSource(controller: self, location: messageNode.view.convert(messageNode.bounds, to: nil).origin.offsetBy(dx: location.x, dy: location.y)))
} else {
source = .extracted(ChatMessagePhoneContextExtractedContentSource(chatNode: self.chatDisplayNode, contentNode: contentNode))
// source = .extracted(ChatMessageContextExtractedContentSource(chatController: self, chatNode: self.chatDisplayNode, engine: self.context.engine, message: message, selectAll: false))
}
var items: [ContextMenuItem] = []
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_AddToContacts, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/AddUser"), color: theme.contextMenu.primaryColor) }, action: { [weak self] c, _ in
guard let self, let c else {
return
}
let basicData = DeviceContactBasicData(firstName: "", lastName: "", phoneNumbers: [
DeviceContactPhoneNumberData(label: "", value: number)
])
let contactData = DeviceContactExtendedData(basicData: basicData, middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
pushContactContextOptionsController(context: self.context, contextController: c, presentationData: self.presentationData, peer: nil, contactData: contactData, parentController: self, push: { [weak self] c in
self?.push(c)
})
}))
)
items.append(.separator)
if let peer {
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_SendMessage, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/MessageBubble"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
guard let self else {
return
}
self.openPeer(peer: peer, navigation: .chat(textInputState: nil, subject: nil, peekData: nil), fromMessage: nil)
}))
)
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_TelegramVoiceCall, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Call"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
guard let self else {
return
}
self.controllerInteraction?.callPeer(peer.id, false)
}))
)
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_TelegramVideoCall, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/VideoCall"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
guard let self else {
return
}
self.controllerInteraction?.callPeer(peer.id, true)
}))
)
} else {
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_InviteToTelegram, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Telegram"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
guard let self else {
return
}
self.inviteToTelegram(numbers: [number])
}))
)
}
if number.hasPrefix("+888") {
} else {
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_CallViaCarrier, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/PhoneCall"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
guard let self else {
return
}
self.openUrl("tel:\(number)", concealed: false)
}))
)
}
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_CopyNumber, icon: { theme in return generateTintedImage(image: UIImage(bundleImageName: "Chat/Context Menu/Copy"), color: theme.contextMenu.primaryColor) }, action: { [weak self] _, f in
f(.default)
guard let self else {
return
}
UIPasteboard.general.string = number
self.present(UndoOverlayController(presentationData: self.presentationData, content: .copy(text: presentationData.strings.Conversation_PhoneCopied), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .current)
}))
)
items.append(.separator)
if let peer {
let avatarSize = CGSize(width: 28.0, height: 28.0)
let avatarSignal = peerAvatarCompleteImage(account: self.context.account, peer: peer, size: avatarSize)
let subtitle = NSMutableAttributedString(string: self.presentationData.strings.Chat_Context_Phone_ViewProfile + " >")
if let range = subtitle.string.range(of: ">"), let arrowImage = UIImage(bundleImageName: "Item List/InlineTextRightArrow") {
subtitle.addAttribute(.attachment, value: arrowImage, range: NSRange(range, in: subtitle.string))
subtitle.addAttribute(.baselineOffset, value: 1.0, range: NSRange(range, in: subtitle.string))
}
items.append(
.action(ContextMenuActionItem(text: peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder), textLayout: .secondLineWithAttributedValue(subtitle), icon: { theme in return nil }, iconSource: ContextMenuActionItemIconSource(size: avatarSize, signal: avatarSignal), iconPosition: .left, action: { [weak self] _, f in
f(.default)
guard let self else {
return
}
self.openPeer(peer: peer, navigation: .info(nil), fromMessage: nil)
}))
)
} else {
let emptyAction: ((ContextMenuActionItem.Action) -> Void)? = nil
items.append(
.action(ContextMenuActionItem(text: self.presentationData.strings.Chat_Context_Phone_NotOnTelegram, textLayout: .multiline, textFont: .small, icon: { _ in return nil }, action: emptyAction))
)
}
self.canReadHistory.set(false)
let controller = ContextController(presentationData: self.presentationData, source: source, items: .single(ContextController.Items(content: .list(items))), recognizer: recognizer, gesture: gesture, disableScreenshots: false)
controller.dismissed = { [weak self] in
self?.canReadHistory.set(true)
}
self.window?.presentInGlobalOverlay(controller)
}
}
private func inviteToTelegram(numbers: [String]) {
if MFMessageComposeViewController.canSendText() {
let composer = MFMessageComposeViewController()
composer.messageComposeDelegate = self
composer.recipients = Array(Set(numbers))
let url = self.presentationData.strings.InviteText_URL
let body = self.presentationData.strings.InviteText_SingleContact(url).string
composer.body = body
self.messageComposeController = composer
if let window = self.view.window {
window.rootViewController?.present(composer, animated: true)
}
}
}
@objc public func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
self.messageComposeController = nil
controller.dismiss(animated: true, completion: nil)
}
}
private final class ChatMessagePhoneContextExtractedContentSource: ContextExtractedContentSource {
let keepInPlace: Bool = false
let ignoreContentTouches: Bool = true
let blurBackground: Bool = true
let adjustContentHorizontally = true
private weak var chatNode: ChatControllerNode?
private let contentNode: ContextExtractedContentContainingNode
var shouldBeDismissed: Signal<Bool, NoError> {
return .single(false)
}
init(chatNode: ChatControllerNode, contentNode: ContextExtractedContentContainingNode) {
self.chatNode = chatNode
self.contentNode = contentNode
}
func takeView() -> ContextControllerTakeViewInfo? {
guard let chatNode = self.chatNode else {
return nil
}
let transition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
transition.updateAlpha(node: self.contentNode.contentNode, alpha: 1.0)
return ContextControllerTakeViewInfo(containingItem: .node(self.contentNode), contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil))
}
func putBack() -> ContextControllerPutBackViewInfo? {
guard let chatNode = self.chatNode else {
return nil
}
let transition = ContainedViewLayoutTransition.animated(duration: 0.2, curve: .easeInOut)
transition.updateAlpha(node: self.contentNode.contentNode, alpha: 0.0, completion: { _ in
self.contentNode.removeFromSupernode()
})
return ContextControllerPutBackViewInfo(contentAreaInScreenSpace: chatNode.convert(chatNode.frameForVisibleArea(), to: nil))
}
}

View File

@ -0,0 +1,303 @@
import Foundation
import UIKit
import SwiftSignalKit
import AsyncDisplayKit
import Display
import Postbox
import TelegramCore
import TelegramPresentationData
import TelegramUIPreferences
import AccountContext
import AppBundle
import AvatarNode
import CheckNode
import Markdown
private let textFont = Font.regular(13.0)
private let boldTextFont = Font.semibold(13.0)
private func formattedText(_ text: String, color: UIColor, textAlignment: NSTextAlignment = .natural) -> NSAttributedString {
return parseMarkdownIntoAttributedString(text, attributes: MarkdownAttributes(body: MarkdownAttributeSet(font: textFont, textColor: color), bold: MarkdownAttributeSet(font: boldTextFont, textColor: color), link: MarkdownAttributeSet(font: textFont, textColor: color), linkAttribute: { _ in return nil}), textAlignment: textAlignment)
}
private final class ChatAgeRestrictionAlertContentNode: AlertContentNode {
private let strings: PresentationStrings
private let title: String
private let text: String
private let titleNode: ImmediateTextNode
private let textNode: ASTextNode
private let alwaysCheckNode: InteractiveCheckNode
private let alwaysLabelNode: ASTextNode
private let actionNodesSeparator: ASDisplayNode
private let actionNodes: [TextAlertContentActionNode]
private let actionVerticalSeparators: [ASDisplayNode]
private var validLayout: CGSize?
override var dismissOnOutsideTap: Bool {
return self.isUserInteractionEnabled
}
var alwaysShow: Bool = false {
didSet {
self.alwaysCheckNode.setSelected(self.alwaysShow, animated: true)
}
}
init(context: AccountContext, theme: AlertControllerTheme, ptheme: PresentationTheme, strings: PresentationStrings, title: String, text: String, actions: [TextAlertAction]) {
self.strings = strings
self.title = title
self.text = text
self.titleNode = ImmediateTextNode()
self.titleNode.displaysAsynchronously = false
self.titleNode.maximumNumberOfLines = 1
self.titleNode.textAlignment = .center
self.textNode = ASTextNode()
self.textNode.displaysAsynchronously = false
self.textNode.maximumNumberOfLines = 0
self.textNode.lineSpacing = 0.1
self.alwaysCheckNode = InteractiveCheckNode(theme: CheckNodeTheme(backgroundColor: theme.accentColor, strokeColor: theme.contrastColor, borderColor: theme.controlBorderColor, overlayBorder: false, hasInset: false, hasShadow: false))
self.alwaysLabelNode = ASTextNode()
self.alwaysLabelNode.maximumNumberOfLines = 2
self.alwaysLabelNode.isUserInteractionEnabled = true
self.actionNodesSeparator = ASDisplayNode()
self.actionNodesSeparator.isLayerBacked = true
self.actionNodes = actions.map { action -> TextAlertContentActionNode in
return TextAlertContentActionNode(theme: theme, action: action)
}
var actionVerticalSeparators: [ASDisplayNode] = []
if actions.count > 1 {
for _ in 0 ..< actions.count - 1 {
let separatorNode = ASDisplayNode()
separatorNode.isLayerBacked = true
actionVerticalSeparators.append(separatorNode)
}
}
self.actionVerticalSeparators = actionVerticalSeparators
super.init()
self.addSubnode(self.titleNode)
self.addSubnode(self.textNode)
self.addSubnode(self.alwaysCheckNode)
self.addSubnode(self.alwaysLabelNode)
self.addSubnode(self.actionNodesSeparator)
for actionNode in self.actionNodes {
self.addSubnode(actionNode)
}
for separatorNode in self.actionVerticalSeparators {
self.addSubnode(separatorNode)
}
self.alwaysCheckNode.valueChanged = { [weak self] value in
if let strongSelf = self {
strongSelf.alwaysShow = !strongSelf.alwaysShow
}
}
self.updateTheme(theme)
}
override func didLoad() {
super.didLoad()
self.alwaysLabelNode.view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(self.alwaysTap(_:))))
}
@objc private func alwaysTap(_ gestureRecognizer: UITapGestureRecognizer) {
if self.alwaysCheckNode.isUserInteractionEnabled {
self.alwaysShow = !self.alwaysShow
}
}
override func updateTheme(_ theme: AlertControllerTheme) {
self.titleNode.attributedText = NSAttributedString(string: self.title, font: Font.semibold(17.0), textColor: theme.primaryColor, paragraphAlignment: .center)
self.textNode.attributedText = NSAttributedString(string: self.text, font: Font.regular(13.0), textColor: theme.primaryColor, paragraphAlignment: .center)
self.alwaysLabelNode.attributedText = formattedText("Always show 18+ media", color: theme.primaryColor)
self.actionNodesSeparator.backgroundColor = theme.separatorColor
for actionNode in self.actionNodes {
actionNode.updateTheme(theme)
}
for separatorNode in self.actionVerticalSeparators {
separatorNode.backgroundColor = theme.separatorColor
}
if let size = self.validLayout {
_ = self.updateLayout(size: size, transition: .immediate)
}
}
override func updateLayout(size: CGSize, transition: ContainedViewLayoutTransition) -> CGSize {
var size = size
size.width = min(size.width, 270.0)
self.validLayout = size
var origin: CGPoint = CGPoint(x: 0.0, y: 17.0)
let titleSize = self.titleNode.updateLayout(CGSize(width: size.width - 32.0, height: size.height))
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - titleSize.width) / 2.0), y: origin.y), size: titleSize))
origin.y += titleSize.height + 6.0
var entriesHeight: CGFloat = 0.0
let textSize = self.textNode.measure(CGSize(width: size.width - 32.0, height: size.height))
transition.updateFrame(node: self.textNode, frame: CGRect(origin: CGPoint(x: floorToScreenPixels((size.width - textSize.width) / 2.0), y: origin.y), size: textSize))
origin.y += textSize.height
if self.alwaysLabelNode.supernode != nil {
origin.y += 21.0
entriesHeight += 21.0
let checkSize = CGSize(width: 22.0, height: 22.0)
let condensedSize = CGSize(width: size.width - 76.0, height: size.height)
let alwaysSize = self.alwaysLabelNode.measure(condensedSize)
let totalWidth = checkSize.width + alwaysSize.width + 12.0
let originX = floorToScreenPixels((size.width - totalWidth) / 2.0)
transition.updateFrame(node: self.alwaysLabelNode, frame: CGRect(origin: CGPoint(x: originX + checkSize.width + 12.0, y: origin.y), size: alwaysSize))
transition.updateFrame(node: self.alwaysCheckNode, frame: CGRect(origin: CGPoint(x: originX, y: origin.y - 2.0), size: checkSize))
origin.y += alwaysSize.height
entriesHeight += alwaysSize.height
}
let actionButtonHeight: CGFloat = 44.0
var minActionsWidth: CGFloat = 0.0
let maxActionWidth: CGFloat = floor(size.width / CGFloat(self.actionNodes.count))
let actionTitleInsets: CGFloat = 8.0
var effectiveActionLayout = TextAlertContentActionLayout.vertical
for actionNode in self.actionNodes {
let actionTitleSize = actionNode.titleNode.updateLayout(CGSize(width: maxActionWidth, height: actionButtonHeight))
if case .horizontal = effectiveActionLayout, actionTitleSize.height > actionButtonHeight * 0.6667 {
effectiveActionLayout = .vertical
}
switch effectiveActionLayout {
case .horizontal:
minActionsWidth += actionTitleSize.width + actionTitleInsets
case .vertical:
minActionsWidth = max(minActionsWidth, actionTitleSize.width + actionTitleInsets)
}
}
let insets = UIEdgeInsets(top: 18.0, left: 18.0, bottom: 18.0, right: 18.0)
let contentWidth = max(size.width, minActionsWidth)
var actionsHeight: CGFloat = 0.0
switch effectiveActionLayout {
case .horizontal:
actionsHeight = actionButtonHeight
case .vertical:
actionsHeight = actionButtonHeight * CGFloat(self.actionNodes.count)
}
let resultSize = CGSize(width: contentWidth, height: titleSize.height + textSize.height + entriesHeight + actionsHeight + 8.0 + insets.top + insets.bottom)
transition.updateFrame(node: self.actionNodesSeparator, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
var actionOffset: CGFloat = 0.0
let actionWidth: CGFloat = floor(resultSize.width / CGFloat(self.actionNodes.count))
var separatorIndex = -1
var nodeIndex = 0
for actionNode in self.actionNodes {
if separatorIndex >= 0 {
let separatorNode = self.actionVerticalSeparators[separatorIndex]
switch effectiveActionLayout {
case .horizontal:
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: actionOffset - UIScreenPixel, y: resultSize.height - actionsHeight), size: CGSize(width: UIScreenPixel, height: actionsHeight - UIScreenPixel)))
case .vertical:
transition.updateFrame(node: separatorNode, frame: CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset - UIScreenPixel), size: CGSize(width: resultSize.width, height: UIScreenPixel)))
}
}
separatorIndex += 1
let currentActionWidth: CGFloat
switch effectiveActionLayout {
case .horizontal:
if nodeIndex == self.actionNodes.count - 1 {
currentActionWidth = resultSize.width - actionOffset
} else {
currentActionWidth = actionWidth
}
case .vertical:
currentActionWidth = resultSize.width
}
let actionNodeFrame: CGRect
switch effectiveActionLayout {
case .horizontal:
actionNodeFrame = CGRect(origin: CGPoint(x: actionOffset, y: resultSize.height - actionsHeight), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
actionOffset += currentActionWidth
case .vertical:
actionNodeFrame = CGRect(origin: CGPoint(x: 0.0, y: resultSize.height - actionsHeight + actionOffset), size: CGSize(width: currentActionWidth, height: actionButtonHeight))
actionOffset += actionButtonHeight
}
transition.updateFrame(node: actionNode, frame: actionNodeFrame)
nodeIndex += 1
}
return resultSize
}
}
public func chatAgeRestrictionAlertController(context: AccountContext, updatedPresentationData: (initial: PresentationData, signal: Signal<PresentationData, NoError>)?, completion: @escaping (Bool) -> Void) -> AlertController {
let theme = defaultDarkColorPresentationTheme
let presentationData: PresentationData
if let updatedPresentationData {
presentationData = updatedPresentationData.initial
} else {
presentationData = context.sharedContext.currentPresentationData.with { $0 }
}
let strings = presentationData.strings
//TODO:localize
var dismissImpl: ((Bool) -> Void)?
var getContentNodeImpl: (() -> ChatAgeRestrictionAlertContentNode?)?
let actions: [TextAlertAction] = [TextAlertAction(type: .defaultAction, title: "View Anyway", action: {
if let alwaysShow = getContentNodeImpl?()?.alwaysShow {
completion(alwaysShow)
} else {
completion(false)
}
dismissImpl?(true)
}), TextAlertAction(type: .genericAction, title: presentationData.strings.Common_Cancel, action: {
dismissImpl?(true)
})]
let title = "18+ Content"
let text = "This media may contain sensitive content suitable only for adults.\nDo you still want to view it?"
let contentNode = ChatAgeRestrictionAlertContentNode(context: context, theme: AlertControllerTheme(presentationData: presentationData), ptheme: theme, strings: strings, title: title, text: text, actions: actions)
getContentNodeImpl = { [weak contentNode] in
return contentNode
}
let controller = AlertController(theme: AlertControllerTheme(presentationData: presentationData), contentNode: contentNode)
dismissImpl = { [weak controller] animated in
if animated {
controller?.dismissAnimated()
} else {
controller?.dismiss()
}
}
return controller
}

View File

@ -123,6 +123,7 @@ import PeerNameColorScreen
import ChatEmptyNode
import ChatMediaInputStickerGridItem
import AdsInfoScreen
import MessageUI
public enum ChatControllerPeekActions {
case standard
@ -224,6 +225,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var validLayout: ContainerViewLayout?
public weak var parentController: ViewController?
public weak var customNavigationController: NavigationController?
let currentChatListFilter: Int32?
let chatNavigationStack: [ChatNavigationStackItem]
@ -593,6 +595,8 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
var networkSpeedEventsDisposable: Disposable?
var messageComposeController: MFMessageComposeViewController?
public var alwaysShowSearchResultsAsList: Bool = false {
didSet {
self.presentationInterfaceState = self.presentationInterfaceState.updatedDisplayHistoryFilterAsList(self.alwaysShowSearchResultsAsList)
@ -2295,27 +2299,28 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
}
}
}, openUrl: { [weak self] urlData in
if let strongSelf = self {
let url = urlData.url
let concealed = urlData.concealed
let message = urlData.message
let progress = urlData.progress
let forceExternal = urlData.external ?? false
var skipConcealedAlert = false
if let author = message?.author, author.isVerified {
skipConcealedAlert = true
}
if let message, let adAttribute = message.attributes.first(where: { $0 is AdMessageAttribute }) as? AdMessageAttribute {
strongSelf.chatDisplayNode.historyNode.adMessagesContext?.markAction(opaqueId: adAttribute.opaqueId)
}
if let performOpenURL = strongSelf.performOpenURL {
performOpenURL(message, url, progress)
} else {
strongSelf.openUrl(url, concealed: concealed, forceExternal: forceExternal, skipConcealedAlert: skipConcealedAlert, message: message, allowInlineWebpageResolution: urlData.allowInlineWebpageResolution, progress: progress)
}
guard let strongSelf = self else {
return
}
let url = urlData.url
let concealed = urlData.concealed
let message = urlData.message
let progress = urlData.progress
let forceExternal = urlData.external ?? false
var skipConcealedAlert = false
if let author = message?.author, author.isVerified {
skipConcealedAlert = true
}
if let message, let adAttribute = message.attributes.first(where: { $0 is AdMessageAttribute }) as? AdMessageAttribute {
strongSelf.chatDisplayNode.historyNode.adMessagesContext?.markAction(opaqueId: adAttribute.opaqueId)
}
if let performOpenURL = strongSelf.performOpenURL {
performOpenURL(message, url, progress)
} else {
strongSelf.openUrl(url, concealed: concealed, forceExternal: forceExternal, skipConcealedAlert: skipConcealedAlert, message: message, allowInlineWebpageResolution: urlData.allowInlineWebpageResolution, progress: progress)
}
}, shareCurrentLocation: { [weak self] in
if let strongSelf = self {
@ -4629,6 +4634,34 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return
}
self.openStickerEditor()
}, openPhoneContextMenu: { [weak self] phoneData in
guard let self else {
return
}
phoneData.progress?.set(.single(true))
let _ = (self.context.engine.peers.resolvePeerByPhone(phone: phoneData.number)
|> deliverOnMainQueue).start(next: { [weak self] peer in
guard let self else {
return
}
phoneData.progress?.set(.single(false))
self.openPhoneContextMenu(number: phoneData.number, peer: peer, message: phoneData.message, contentNode: phoneData.contentNode, messageNode: phoneData.messageNode, frame: phoneData.messageNode.bounds, anyRecognizer: nil, location: nil)
})
}, openAgeRestrictedMessageMedia: { [weak self] message, reveal in
guard let self else {
return
}
let controller = chatAgeRestrictionAlertController(context: self.context, updatedPresentationData: self.updatedPresentationData, completion: { [weak self] alwaysShow in
guard let self else {
return
}
if alwaysShow {
self.present(UndoOverlayController(presentationData: self.presentationData, content: .info(title: nil, text: "You can update the visibility of sensitive media in [Data and Storage > Show 18+ Content]().", timeout: nil, customUndoText: nil), elevatedLayout: false, position: .top, action: { _ in return false }), in: .current)
}
reveal()
})
self.present(controller, in: .window(.root))
}, playMessageEffect: { [weak self] message in
guard let self else {
return
@ -9525,7 +9558,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
func addPeerContact() {
if let peer = self.presentationInterfaceState.renderedPeer?.chatMainPeer as? TelegramUser, let peerStatusSettings = self.presentationInterfaceState.contactStatus?.peerStatusSettings, let contactData = DeviceContactExtendedData(peer: EnginePeer(peer)) {
self.present(context.sharedContext.makeDeviceContactInfoController(context: context, subject: .create(peer: peer, contactData: contactData, isSharing: true, shareViaException: peerStatusSettings.contains(.addExceptionWhenAddingContact), completion: { [weak self] peer, stableId, contactData in
self.present(context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: self.context), environment: ShareControllerAppEnvironment(sharedContext: self.context.sharedContext), subject: .create(peer: peer, contactData: contactData, isSharing: true, shareViaException: peerStatusSettings.contains(.addExceptionWhenAddingContact), completion: { [weak self] peer, stableId, contactData in
guard let strongSelf = self else {
return
}
@ -10570,6 +10603,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} else if case let .overlay(navigationController) = self.presentationInterfaceState.mode {
return navigationController
} else {
if let navigationController = self.customNavigationController {
return navigationController
}
return nil
}
}

View File

@ -32,6 +32,7 @@ import TelegramCallsUI
import AutomaticBusinessMessageSetupScreen
import MediaEditorScreen
import CameraScreen
import ShareController
extension ChatControllerImpl {
enum AttachMenuSubject {
@ -520,7 +521,7 @@ extension ChatControllerImpl {
enqueueMessages.append(.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: strongSelf.chatLocation.threadId, replyToMessageId: replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
strongSelf.sendMessages(strongSelf.transformEnqueueMessages(enqueueMessages, silentPosting: silent, scheduleTime: scheduleTime))
} else {
let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in
let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in
guard let strongSelf = self, !contactData.basicData.phoneNumbers.isEmpty else {
return
}
@ -1590,7 +1591,7 @@ extension ChatControllerImpl {
let message = EnqueueMessage.message(text: "", attributes: [], inlineStickers: [:], mediaReference: .standalone(media: media), threadId: strongSelf.chatLocation.threadId, replyToMessageId: replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: [])
strongSelf.sendMessages([message])
} else {
let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in
let contactController = strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .filter(peer: peerAndContactData.0, contactId: nil, contactData: contactData, completion: { peer, contactData in
guard let strongSelf = self, !contactData.basicData.phoneNumbers.isEmpty else {
return
}

View File

@ -176,7 +176,8 @@ extension ChatControllerImpl {
}), in: .current)
}
self.push(calendarScreen)
self.effectiveNavigationController?.pushViewController(calendarScreen)
dismissCalendarScreen = { [weak calendarScreen] in
calendarScreen?.dismiss(completion: nil)
}

View File

@ -13,6 +13,7 @@ import SearchUI
import TelegramPermissionsUI
import AppBundle
import DeviceAccess
import ShareController
public class ComposeControllerImpl: ViewController, ComposeController {
private let context: AccountContext
@ -200,7 +201,7 @@ public class ComposeControllerImpl: ViewController, ComposeController {
switch status {
case .allowed:
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: "", lastName: "", phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!<Mobile>!$_", value: "+")]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
(strongSelf.navigationController as? NavigationController)?.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
(strongSelf.navigationController as? NavigationController)?.pushViewController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
guard let strongSelf = self else {
return
}
@ -211,7 +212,7 @@ public class ComposeControllerImpl: ViewController, ComposeController {
}
}
} else {
(strongSelf.navigationController as? NavigationController)?.replaceAllButRootController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: strongSelf.context, subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil), animated: true)
(strongSelf.navigationController as? NavigationController)?.replaceAllButRootController(strongSelf.context.sharedContext.makeDeviceContactInfoController(context: ShareControllerAppAccountContext(context: strongSelf.context), environment: ShareControllerAppEnvironment(sharedContext: strongSelf.context.sharedContext), subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil), animated: true)
}
}), completed: nil, cancelled: nil))
case .notDetermined:

View File

@ -7,6 +7,7 @@ import AccountContext
import AlertUI
import PresentationDataUtils
import PeerInfoUI
import ShareController
func openAddContactImpl(context: AccountContext, firstName: String = "", lastName: String = "", phoneNumber: String, label: String = "_$!<Mobile>!$_", present: @escaping (ViewController, Any?) -> Void, pushController: @escaping (ViewController) -> Void, completed: @escaping () -> Void = {}) {
let _ = (DeviceAccess.authorizationStatus(subject: .contacts)
@ -15,13 +16,13 @@ func openAddContactImpl(context: AccountContext, firstName: String = "", lastNam
switch value {
case .allowed:
let contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: firstName, lastName: lastName, phoneNumbers: [DeviceContactPhoneNumberData(label: label, value: phoneNumber)]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
present(deviceContactInfoController(context: context, subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
present(deviceContactInfoController(context: ShareControllerAppAccountContext(context: context), environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), subject: .create(peer: nil, contactData: contactData, isSharing: false, shareViaException: false, completion: { peer, stableId, contactData in
if let peer = peer {
if let infoController = context.sharedContext.makePeerInfoController(context: context, updatedPresentationData: nil, peer: peer, mode: .generic, avatarInitiallyExpanded: false, fromChat: false, requestsContext: nil) {
pushController(infoController)
}
} else {
pushController(deviceContactInfoController(context: context, subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil))
pushController(deviceContactInfoController(context: ShareControllerAppAccountContext(context: context), environment: ShareControllerAppEnvironment(sharedContext: context.sharedContext), subject: .vcard(nil, stableId, contactData), completed: nil, cancelled: nil))
}
}), completed: completed, cancelled: nil), ViewControllerPresentationArguments(presentationAnimation: .modalSheet))
case .notDetermined:

View File

@ -330,7 +330,7 @@ func openChatMessageImpl(_ params: OpenChatMessageParams) -> Bool {
} else {
contactData = DeviceContactExtendedData(basicData: DeviceContactBasicData(firstName: contact.firstName, lastName: contact.lastName, phoneNumbers: [DeviceContactPhoneNumberData(label: "_$!<Mobile>!$_", value: contact.phoneNumber)]), middleName: "", prefix: "", suffix: "", organization: "", jobTitle: "", department: "", emailAddresses: [], urls: [], addresses: [], birthdayDate: nil, socialProfiles: [], instantMessagingProfiles: [], note: "")
}
let controller = deviceContactInfoController(context: params.context, updatedPresentationData: params.updatedPresentationData, subject: .vcard(peer?._asPeer(), nil, contactData), completed: nil, cancelled: nil)
let controller = deviceContactInfoController(context: ShareControllerAppAccountContext(context: params.context), environment: ShareControllerAppEnvironment(sharedContext: params.context.sharedContext), updatedPresentationData: params.updatedPresentationData, subject: .vcard(peer?._asPeer(), nil, contactData), completed: nil, cancelled: nil)
params.navigationController?.pushViewController(controller)
})
return true

View File

@ -175,6 +175,8 @@ final class OverlayAudioPlayerControllerNode: ViewControllerTracingNode, ASGestu
}, openRecommendedChannelContextMenu: { _, _, _ in
}, openGroupBoostInfo: { _, _ in
}, openStickerEditor: {
}, openPhoneContextMenu: { _ in
}, openAgeRestrictedMessageMedia: { _, _ in
}, playMessageEffect: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {

View File

@ -1600,8 +1600,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
openResolvedUrlImpl(resolvedUrl, context: context, urlContext: urlContext, navigationController: navigationController, forceExternal: forceExternal, openPeer: openPeer, sendFile: sendFile, sendSticker: sendSticker, sendEmoji: sendEmoji, requestMessageActionUrlAuth: requestMessageActionUrlAuth, joinVoiceChat: joinVoiceChat, present: present, dismissInput: dismissInput, contentContext: contentContext, progress: progress, completion: completion)
}
public func makeDeviceContactInfoController(context: AccountContext, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController {
return deviceContactInfoController(context: context, subject: subject, completed: completed, cancelled: cancelled)
public func makeDeviceContactInfoController(context: ShareControllerAccountContext, environment: ShareControllerEnvironment, subject: DeviceContactInfoSubject, completed: (() -> Void)?, cancelled: (() -> Void)?) -> ViewController {
return deviceContactInfoController(context: context, environment: environment, subject: subject, completed: completed, cancelled: cancelled)
}
public func makePeersNearbyController(context: AccountContext) -> ViewController {
@ -1771,6 +1771,8 @@ public final class SharedAccountContextImpl: SharedAccountContext {
}, openRecommendedChannelContextMenu: { _, _, _ in
}, openGroupBoostInfo: { _, _ in
}, openStickerEditor: {
}, openPhoneContextMenu: { _ in
}, openAgeRestrictedMessageMedia: { _, _ in
}, playMessageEffect: { _ in
}, requestMessageUpdate: { _, _ in
}, cancelInteractiveKeyboardGestures: {

View File

@ -234,24 +234,22 @@ public struct WebAppParameters {
}
}
public func generateWebAppThemeParams(_ presentationTheme: PresentationTheme) -> [String: Any] {
let backgroundColor = presentationTheme.list.plainBackgroundColor.rgb
let secondaryBackgroundColor = presentationTheme.list.blocksBackgroundColor.rgb
public func generateWebAppThemeParams(_ theme: PresentationTheme) -> [String: Any] {
return [
"bg_color": Int32(bitPattern: backgroundColor),
"secondary_bg_color": Int32(bitPattern: secondaryBackgroundColor),
"text_color": Int32(bitPattern: presentationTheme.list.itemPrimaryTextColor.rgb),
"hint_color": Int32(bitPattern: presentationTheme.list.itemSecondaryTextColor.rgb),
"link_color": Int32(bitPattern: presentationTheme.list.itemAccentColor.rgb),
"button_color": Int32(bitPattern: presentationTheme.list.itemCheckColors.fillColor.rgb),
"button_text_color": Int32(bitPattern: presentationTheme.list.itemCheckColors.foregroundColor.rgb),
"header_bg_color": Int32(bitPattern: presentationTheme.rootController.navigationBar.opaqueBackgroundColor.rgb),
"accent_text_color": Int32(bitPattern: presentationTheme.list.itemAccentColor.rgb),
"section_bg_color": Int32(bitPattern: presentationTheme.list.itemBlocksBackgroundColor.rgb),
"section_header_text_color": Int32(bitPattern: presentationTheme.list.freeTextColor.rgb),
"subtitle_text_color": Int32(bitPattern: presentationTheme.list.itemSecondaryTextColor.rgb),
"destructive_text_color": Int32(bitPattern: presentationTheme.list.itemDestructiveColor.rgb),
"section_separator_color": Int32(bitPattern: presentationTheme.list.itemBlocksSeparatorColor.rgb)
"bg_color": Int32(bitPattern: theme.list.plainBackgroundColor.rgb),
"secondary_bg_color": Int32(bitPattern: theme.list.blocksBackgroundColor.rgb),
"text_color": Int32(bitPattern: theme.list.itemPrimaryTextColor.rgb),
"hint_color": Int32(bitPattern: theme.list.itemSecondaryTextColor.rgb),
"link_color": Int32(bitPattern: theme.list.itemAccentColor.rgb),
"button_color": Int32(bitPattern: theme.list.itemCheckColors.fillColor.rgb),
"button_text_color": Int32(bitPattern: theme.list.itemCheckColors.foregroundColor.rgb),
"header_bg_color": Int32(bitPattern: theme.rootController.navigationBar.opaqueBackgroundColor.rgb),
"accent_text_color": Int32(bitPattern: theme.list.itemAccentColor.rgb),
"section_bg_color": Int32(bitPattern: theme.list.itemBlocksBackgroundColor.rgb),
"section_header_text_color": Int32(bitPattern: theme.list.freeTextColor.rgb),
"subtitle_text_color": Int32(bitPattern: theme.list.itemSecondaryTextColor.rgb),
"destructive_text_color": Int32(bitPattern: theme.list.itemDestructiveColor.rgb),
"section_separator_color": Int32(bitPattern: theme.list.itemBlocksSeparatorColor.rgb)
]
}