This commit is contained in:
isaac 2026-05-15 19:07:27 +08:00
parent 50da64adfa
commit 13a153aff2
67 changed files with 64681 additions and 62438 deletions

View file

@ -333,7 +333,7 @@ private enum MarkdownTaskListState {
private final class MarkdownConversionContext {
private let context: AccountContext
fileprivate let documentURL: URL
fileprivate let documentURL: URL?
fileprivate let formulasByPlaceholder: [String: MarkdownFormulaDescriptor]
fileprivate let budget: MarkdownConversionBudget
private var nextRemoteMediaId: Int64 = 0
@ -341,7 +341,7 @@ private final class MarkdownConversionContext {
private(set) var media: [EngineMedia.Id: EngineRawMedia] = [:]
init(context: AccountContext, documentURL: URL, formulasByPlaceholder: [String: MarkdownFormulaDescriptor], budget: MarkdownConversionBudget) {
init(context: AccountContext, documentURL: URL?, formulasByPlaceholder: [String: MarkdownFormulaDescriptor], budget: MarkdownConversionBudget) {
self.context = context
self.documentURL = documentURL
self.formulasByPlaceholder = formulasByPlaceholder
@ -977,14 +977,27 @@ func markdownWebpage(context: AccountContext, file: FileMediaReference) -> (webP
guard let data = try? Data(contentsOf: fileURL) else {
return nil
}
guard let webPage = markdownWebpage(context: context, file: file, fileURL: fileURL, data: data) else {
guard let webPage = markdownWebpage(context: context, file: (file, fileURL), data: data) else {
return nil
}
return (webPage, fileURL)
}
public func inputRichTextAttributeFromText(context: AccountContext, text: String) -> RichTextMessageAttribute? {
guard #available(iOS 15.0, *) else {
return nil
}
guard let data = text.data(using: .utf8) else {
return nil
}
guard let webpage = markdownWebpage(context: context, file: nil, data: data), case let .Loaded(content) = webpage.content, let instantPage = content.instantPage else {
return nil
}
return RichTextMessageAttribute(instantPage: instantPage._parse())
}
@available(iOS 15.0, *)
private func markdownWebpage(context: AccountContext, file: FileMediaReference, fileURL: URL, data: Data) -> TelegramMediaWebpage? {
private func markdownWebpage(context: AccountContext, file: (file: FileMediaReference, url: URL)?, data: Data) -> TelegramMediaWebpage? {
let limits = markdownSafetyLimits
guard markdownPassesPreflight(data: data, limits: limits) else {
return nil
@ -996,17 +1009,23 @@ private func markdownWebpage(context: AccountContext, file: FileMediaReference,
let attributedString: NSAttributedString
do {
let baseURL: URL?
if let file {
baseURL = file.url.deletingLastPathComponent()
} else {
baseURL = nil
}
attributedString = try NSAttributedString(
markdown: Data(preparedSource.text.utf8),
options: .init(),
baseURL: fileURL.deletingLastPathComponent()
baseURL: baseURL
)
} catch {
return nil
}
let budget = MarkdownConversionBudget(limits: limits)
let conversionContext = MarkdownConversionContext(context: context, documentURL: fileURL, formulasByPlaceholder: preparedSource.formulasByPlaceholder, budget: budget)
let conversionContext = MarkdownConversionContext(context: context, documentURL: file?.url, formulasByPlaceholder: preparedSource.formulasByPlaceholder, budget: budget)
guard let pageResult = markdownPageResult(from: attributedString, context: conversionContext) else {
return nil
}
@ -1015,14 +1034,17 @@ private func markdownWebpage(context: AccountContext, file: FileMediaReference,
return nil
}
let title = markdownTitle(from: blocks, file: file, fileURL: fileURL)
var title: String?
if let file {
title = markdownTitle(from: blocks, file: file.file, fileURL: file.url)
}
let text = markdownFirstParagraphText(from: blocks)
let instantPage = InstantPage(
blocks: blocks,
media: pageResult.media,
isComplete: true,
rtl: false,
url: fileURL.absoluteString,
url: file?.url.absoluteString ?? "",
views: nil
)
@ -1030,8 +1052,8 @@ private func markdownWebpage(context: AccountContext, file: FileMediaReference,
webpageId: EngineMedia.Id(namespace: 0, id: 0),
content: .Loaded(
TelegramMediaWebpageLoadedContent(
url: fileURL.absoluteString,
displayUrl: fileURL.absoluteString,
url: file?.url.absoluteString ?? "",
displayUrl: file?.url.absoluteString ?? "",
hash: 0,
type: "article",
websiteName: nil,
@ -1764,7 +1786,7 @@ private func markdownInlineImageDimensions(attributes: [NSAttributedString.Key:
return PixelDimensions(width: side, height: side)
}
private func markdownLink(attributes: [NSAttributedString.Key: Any], documentURL: URL) -> String? {
private func markdownLink(attributes: [NSAttributedString.Key: Any], documentURL: URL?) -> String? {
if let value = attributes[markdownLinkAttribute] as? URL {
return markdownNormalizedLink(value, documentURL: documentURL)
}
@ -1783,14 +1805,14 @@ private func markdownLink(attributes: [NSAttributedString.Key: Any], documentURL
return nil
}
private func markdownNormalizedLink(_ url: URL, documentURL: URL) -> String {
private func markdownNormalizedLink(_ url: URL, documentURL: URL?) -> String {
if url.baseURL != nil {
let relative = url.relativeString
if relative.hasPrefix("#") {
return relative
}
}
if let fragment = url.fragment, markdownMatchesDocument(url, documentURL: documentURL) {
if let documentURL, let fragment = url.fragment, markdownMatchesDocument(url, documentURL: documentURL) {
return "#\(fragment)"
}
return url.absoluteString

View file

@ -77,6 +77,176 @@ private func paidContentGroupType(paidContent: TelegramMediaPaidContent) -> Mess
return currentType
}
extension RichText {
func previewText() -> String {
switch self {
case .empty:
return ""
case let .plain(value):
return value
case let .bold(value):
return value.previewText()
case let .italic(value):
return value.previewText()
case let .underline(value):
return value.previewText()
case let .strikethrough(value):
return value.previewText()
case let .fixed(value):
return value.previewText()
case let .url(value, _, _):
return value.previewText()
case let .email(value, _):
return value.previewText()
case let .concat(values):
var result = ""
for value in values {
result.append(value.previewText())
}
return result
case let .`subscript`(value):
return value.previewText()
case let .superscript(value):
return value.previewText()
case let .marked(value):
return value.previewText()
case let .phone(value, _):
return value.previewText()
case .image:
//TODO:localize
return "Photo"
case let .anchor(value, _):
return value.previewText()
case let .formula(latex):
return latex
}
}
}
extension InstantPageListItem {
func previewText() -> String {
switch self {
case .unknown:
return ""
case let .text(text, num):
if let num, !num.isEmpty {
return "\(num). \(text.previewText())"
} else {
return text.previewText()
}
case let .blocks(blocks, num):
var blocksText = ""
for block in blocks {
if !blocksText.isEmpty {
blocksText.append("\n")
}
blocksText.append(block.previewText())
}
if let num {
return "\(num). \(blocksText)"
} else {
return blocksText
}
}
}
}
extension InstantPageBlock {
func previewText() -> String {
switch self {
case .unsupported:
return ""
case let .title(text):
return text.previewText()
case let .subtitle(text):
return text.previewText()
case let .authorDate(author, _):
return author.previewText()
case let .header(text):
return text.previewText()
case let .subheader(text):
return text.previewText()
case let .heading(text, _):
return text.previewText()
case let .formula(latex):
return latex
case let .paragraph(text):
return text.previewText()
case let .preformatted(text, _):
return text.previewText()
case let .footer(text):
return text.previewText()
case .divider:
return "\n"
case .anchor:
return ""
case let .list(items, _):
var result = ""
for item in items {
if !result.isEmpty {
result.append("\n")
}
result.append(item.previewText())
}
return result
case let .blockQuote(text, caption):
return text.previewText() + caption.previewText()
case let .pullQuote(text, caption):
return text.previewText() + caption.previewText()
case .image(_, _, _, _):
//TODO:localize
return "Photo"
case .video(_, _, _, _):
//TODO:localize
return "Video"
case .audio:
//TODO:localize
return "Audio"
case .cover:
return ""
case .webEmbed:
return ""
case .postEmbed:
return ""
case .collage:
return ""
case .slideshow:
return ""
case .channelBanner:
return ""
case .kicker:
return ""
case .table:
//TODO:localize
return "Table"
case .details:
return ""
case .relatedArticles:
return ""
case .map:
//TODO:localize
return "Map"
}
}
}
extension InstantPage {
func previewText() -> String {
let maxLength: Int = 200
var result = ""
for block in self.blocks {
if !result.isEmpty {
result.append("\n")
}
result.append(block.previewText())
if result.count > maxLength {
break
}
}
return result
}
}
public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, contentSettings: ContentSettings, messages: [EngineMessage], chatPeer: EngineRenderedPeer, accountPeerId: EnginePeer.Id, enableMediaEmoji: Bool = true, isPeerGroup: Bool = false) -> (peer: EnginePeer?, hideAuthor: Bool, messageText: String, messageEntities: [MessageTextEntity], spoilers: [NSRange]?, customEmojiRanges: [(NSRange, ChatTextInputTextCustomEmojiAttribute)]?) {
let peer: EnginePeer?
@ -103,7 +273,10 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
messageText = ""
for message in messages {
if !message.text.isEmpty {
if let richText = message.richText {
messageText = richText.instantPage.previewText()
messageEntities = []
} else if !message.text.isEmpty {
messageText = message.text
messageEntities = message._asMessage().textEntitiesAttribute?.entities ?? []
for entity in messageEntities {

View file

@ -165,7 +165,7 @@ private func instantPageFirstTextLineMidY(in items: [InstantPageItem]) -> CGFloa
return nil
}
public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation: MediaResourceUserLocation, rtl: Bool, block: InstantPageBlock, boundingWidth: CGFloat, horizontalInset: CGFloat, safeInset: CGFloat, isCover: Bool, previousItems: [InstantPageItem], fillToSize: CGSize?, media: [EngineMedia.Id: EngineMedia], mediaIndexCounter: inout Int, embedIndexCounter: inout Int, detailsIndexCounter: inout Int, theme: InstantPageTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, webEmbedHeights: [Int : CGFloat] = [:], cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil, excludeCaptions: Bool, isLast: Bool) -> InstantPageLayout {
public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation: MediaResourceUserLocation, rtl: Bool, block: InstantPageBlock, boundingWidth: CGFloat, horizontalInset: CGFloat, safeInset: CGFloat, isCover: Bool, previousItems: [InstantPageItem], fillToSize: CGSize?, media: [EngineMedia.Id: EngineMedia], mediaIndexCounter: inout Int, embedIndexCounter: inout Int, detailsIndexCounter: inout Int, theme: InstantPageTheme, strings: PresentationStrings, dateTimeFormat: PresentationDateTimeFormat, webEmbedHeights: [Int : CGFloat] = [:], cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil, excludeCaptions: Bool, isLast: Bool, fitToWidth: Bool) -> InstantPageLayout {
let layoutCaption: (InstantPageCaption, CGSize) -> ([InstantPageItem], CGSize) = { caption, contentSize in
var items: [InstantPageItem] = []
var offset = contentSize.height
@ -177,7 +177,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
offset += 14.0
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .caption, link: false)
let (textItem, captionItems, captionContentSize) = layoutTextItemWithString(attributedStringForRichText(caption.text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: offset), media: media, webpage: webpage)
let (textItem, captionItems, captionContentSize) = layoutTextItemWithString(attributedStringForRichText(caption.text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: offset), media: media, webpage: webpage, fitToWidth: fitToWidth)
contentSize.height += captionContentSize.height
offset += captionContentSize.height
items.append(contentsOf: captionItems)
@ -196,7 +196,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
}
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .credit, link: false)
let (_, captionItems, captionContentSize) = layoutTextItemWithString(attributedStringForRichText(caption.credit, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, alignment: rtl ? .right : .natural, offset: CGPoint(x: horizontalInset, y: offset), media: media, webpage: webpage)
let (_, captionItems, captionContentSize) = layoutTextItemWithString(attributedStringForRichText(caption.credit, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, alignment: rtl ? .right : .natural, offset: CGPoint(x: horizontalInset, y: offset), media: media, webpage: webpage, fitToWidth: fitToWidth)
contentSize.height += captionContentSize.height
offset += captionContentSize.height
items.append(contentsOf: captionItems)
@ -217,16 +217,16 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
switch block {
case let .cover(block):
return layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: block, boundingWidth: boundingWidth, horizontalInset: horizontalInset, safeInset: safeInset, isCover: true, previousItems:previousItems, fillToSize: fillToSize, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: true)
return layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: block, boundingWidth: boundingWidth, horizontalInset: horizontalInset, safeInset: safeInset, isCover: true, previousItems:previousItems, fillToSize: fillToSize, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: true, fitToWidth: fitToWidth)
case let .title(text):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .header, link: false)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .subtitle(text):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .subheader, link: false)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .authorDate(author: author, date: date):
let styleStack = InstantPageTextStyleStack()
@ -265,7 +265,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
if let previousItem = previousItems.last as? InstantPageTextItem, previousItem.containsRTL {
previousItemHasRTL = true
}
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, alignment: rtl || previousItemHasRTL ? .right : .natural, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, alignment: rtl || previousItemHasRTL ? .right : .natural, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
} else {
return InstantPageLayout(origin: CGPoint(), contentSize: CGSize(), items: [])
@ -273,22 +273,22 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
case let .kicker(text):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .kicker, link: false)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .header(text):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .header, link: false)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .subheader(text):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .subheader, link: false)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .heading(text, level):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, attributes: theme.headingTextAttributes(level: level, link: false))
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .formula(latex):
let styleStack = InstantPageTextStyleStack()
@ -298,7 +298,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
let fontSize = (attributes[NSAttributedString.Key.font] as? UIFont)?.pointSize ?? theme.textCategories.paragraph.font.size
guard let attachment = instantPageMathAttachment(latex: latex, fontSize: fontSize, textColor: textColor, mode: .block) else {
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(.plain(latex), styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(.plain(latex), styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
}
@ -324,7 +324,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
case let .paragraph(text):
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, horizontalInset: horizontalInset, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage)
let (_, items, contentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, horizontalInset: horizontalInset, offset: CGPoint(x: horizontalInset, y: 0.0), media: media, webpage: webpage, fitToWidth: fitToWidth)
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
case let .preformatted(text, language):
let backgroundInset: CGFloat = 14.0
@ -342,6 +342,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
offset: CGPoint(x: 17.0, y: backgroundInset),
media: media,
webpage: webpage,
fitToWidth: fitToWidth,
opaqueBackground: true
)
let backgroundItem = InstantPageShapeItem(frame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: contentSize.height + backgroundInset * 2.0)), shapeFrame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: contentSize.height + backgroundInset * 2.0)), shape: .rect, color: theme.codeBlockBackgroundColor)
@ -407,7 +408,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
} else {
value = "\(i + 1)."
}
let (textItem, _, _) = layoutTextItemWithString(attributedStringForRichText(.plain(value), styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint())
let (textItem, _, _) = layoutTextItemWithString(attributedStringForRichText(.plain(value), styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, offset: CGPoint(), fitToWidth: fitToWidth)
if let textItem = textItem, let line = textItem.lines.first {
textItem.selectable = false
maxIndexWidth = max(maxIndexWidth, line.frame.width)
@ -420,8 +421,12 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
}
let indexSpacing: CGFloat = ordered ? (hasTaskMarkers ? 16.0 : 12.0) : (hasTaskMarkers ? 24.0 : 20.0)
for (i, item) in contentItems.enumerated() {
if (i != 0) {
contentSize.height += 18.0
if i != 0 {
if fitToWidth {
contentSize.height += 12.0
} else {
contentSize.height += 18.0
}
}
let styleStack = InstantPageTextStyleStack()
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)
@ -432,7 +437,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
}
switch effectiveItem {
case let .text(text, _):
let (textItem, textItems, textItemSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - indexSpacing - maxIndexWidth, offset: CGPoint(x: horizontalInset + indexSpacing + maxIndexWidth, y: contentSize.height), media: media, webpage: webpage)
let (textItem, textItems, textItemSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - indexSpacing - maxIndexWidth, offset: CGPoint(x: horizontalInset + indexSpacing + maxIndexWidth, y: contentSize.height), media: media, webpage: webpage, fitToWidth: fitToWidth)
contentSize.height += textItemSize.height
let indexItem = indexItems[i]
@ -467,9 +472,9 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
var firstBlockLineMidY: CGFloat?
for i in 0 ..< blocks.count {
let subBlock = blocks[i]
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subBlock, boundingWidth: boundingWidth - horizontalInset * 2.0 - indexSpacing - maxIndexWidth, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: listItems, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == blocks.count - 1)
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subBlock, boundingWidth: boundingWidth - horizontalInset * 2.0 - indexSpacing - maxIndexWidth, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: listItems, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == blocks.count - 1, fitToWidth: fitToWidth)
let spacing: CGFloat = previousBlock != nil && subLayout.contentSize.height > 0.0 ? spacingBetweenBlocks(upper: previousBlock, lower: subBlock) : 0.0
let spacing: CGFloat = previousBlock != nil && subLayout.contentSize.height > 0.0 ? spacingBetweenBlocks(upper: previousBlock, lower: subBlock, fitToWidth: fitToWidth) : 0.0
let blockItems = subLayout.flattenedItemsWithOrigin(CGPoint(x: horizontalInset + indexSpacing + maxIndexWidth, y: contentSize.height + spacing))
if previousBlock == nil {
originY += spacing
@ -520,7 +525,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)
styleStack.push(.italic)
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - lineInset, offset: CGPoint(x: horizontalInset + lineInset, y: contentSize.height), media: media, webpage: webpage)
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - lineInset, offset: CGPoint(x: horizontalInset + lineInset, y: contentSize.height), media: media, webpage: webpage, fitToWidth: fitToWidth)
contentSize.height += textContentSize.height
items.append(contentsOf: textItems)
@ -554,7 +559,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)
styleStack.push(.italic)
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, alignment: .center, offset: CGPoint(x: 0.0, y: contentSize.height), media: media, webpage: webpage)
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(text, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0, alignment: .center, offset: CGPoint(x: 0.0, y: contentSize.height), media: media, webpage: webpage, fitToWidth: fitToWidth)
for var item in textItems {
item.frame = item.frame.offsetBy(dx: horizontalInset, dy: 0.0)
}
@ -684,7 +689,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
var i = 0
for subItem in innerItems {
let frame = mosaicLayout[i].0
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subItem, boundingWidth: frame.width, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: items, fillToSize: frame.size, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: true, isLast: false)
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subItem, boundingWidth: frame.width, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: items, fillToSize: frame.size, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: true, isLast: false, fitToWidth: false)
items.append(contentsOf: subLayout.flattenedItemsWithOrigin(frame.origin))
i += 1
}
@ -731,7 +736,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)
styleStack.push(.bold)
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(.plain(author), styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - lineInset - avatarInset, offset: CGPoint(x: horizontalInset + lineInset + avatarInset, y: contentSize.height + avatarVerticalInset), media: media, webpage: webpage)
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(.plain(author), styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - lineInset - avatarInset, offset: CGPoint(x: horizontalInset + lineInset + avatarInset, y: contentSize.height + avatarVerticalInset), media: media, webpage: webpage, fitToWidth: fitToWidth)
items.append(contentsOf: textItems)
contentSize.height += textContentSize.height + avatarVerticalInset
@ -759,9 +764,9 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
var previousBlock: InstantPageBlock?
for i in 0 ..< blocks.count {
let subBlock = blocks[i]
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subBlock, boundingWidth: boundingWidth - horizontalInset * 2.0 - lineInset, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: items, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == blocks.count - 1)
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subBlock, boundingWidth: boundingWidth - horizontalInset * 2.0 - lineInset, horizontalInset: 0.0, safeInset: 0.0, isCover: false, previousItems: items, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == blocks.count - 1, fitToWidth: fitToWidth)
let spacing = spacingBetweenBlocks(upper: previousBlock, lower: subBlock)
let spacing = spacingBetweenBlocks(upper: previousBlock, lower: subBlock, fitToWidth: false)
let blockItems = subLayout.flattenedItemsWithOrigin(CGPoint(x: horizontalInset + lineInset, y: contentSize.height + spacing))
items.append(contentsOf: blockItems)
contentSize.height += subLayout.contentSize.height + spacing
@ -943,9 +948,9 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
var previousBlock: InstantPageBlock?
for i in 0 ..< blocks.count {
let subBlock = blocks[i]
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subBlock, boundingWidth: boundingWidth, horizontalInset: horizontalInset, safeInset: safeInset, isCover: false, previousItems: subitems, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &subDetailsIndex, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == blocks.count - 1)
let subLayout = layoutInstantPageBlock(webpage: webpage, userLocation: userLocation, rtl: rtl, block: subBlock, boundingWidth: boundingWidth, horizontalInset: horizontalInset, safeInset: safeInset, isCover: false, previousItems: subitems, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &subDetailsIndex, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == blocks.count - 1, fitToWidth: fitToWidth)
let spacing = spacingBetweenBlocks(upper: previousBlock, lower: subBlock)
let spacing = spacingBetweenBlocks(upper: previousBlock, lower: subBlock, fitToWidth: false)
let blockItems = subLayout.flattenedItemsWithOrigin(CGPoint(x: 0.0, y: contentSize.height + spacing))
subitems.append(contentsOf: blockItems)
contentSize.height += subLayout.contentSize.height + spacing
@ -953,7 +958,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
}
if !blocks.isEmpty {
let closingSpacing = spacingBetweenBlocks(upper: previousBlock, lower: nil)
let closingSpacing = spacingBetweenBlocks(upper: previousBlock, lower: nil, fitToWidth: false)
contentSize.height += closingSpacing
}
@ -971,7 +976,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
setupStyleStack(styleStack, theme: theme, category: .paragraph, link: false)
styleStack.push(.bold)
let backgroundInset: CGFloat = 14.0
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(title, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - backgroundInset * 2.0, offset: CGPoint(x: horizontalInset, y: backgroundInset), media: media, webpage: webpage, opaqueBackground: true)
let (_, textItems, textContentSize) = layoutTextItemWithString(attributedStringForRichText(title, styleStack: styleStack), boundingWidth: boundingWidth - horizontalInset * 2.0 - backgroundInset * 2.0, offset: CGPoint(x: horizontalInset, y: backgroundInset), media: media, webpage: webpage, fitToWidth: fitToWidth, opaqueBackground: true)
let backgroundItem = InstantPageShapeItem(frame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: textContentSize.height + backgroundInset * 2.0)), shapeFrame: CGRect(origin: CGPoint(), size: CGSize(width: boundingWidth, height: textContentSize.height + backgroundInset * 2.0)), shape: .rect, color: theme.panelBackgroundColor)
items.append(backgroundItem)
items.append(contentsOf: textItems)
@ -1054,7 +1059,7 @@ public func layoutInstantPageBlock(webpage: TelegramMediaWebpage, userLocation:
}
}
public func instantPageLayoutForWebPage(_ webPage: TelegramMediaWebpage, instantPage: InstantPage?, userLocation: MediaResourceUserLocation, boundingWidth: CGFloat, sideInset: CGFloat, safeInset: CGFloat, strings: PresentationStrings, theme: InstantPageTheme, dateTimeFormat: PresentationDateTimeFormat, webEmbedHeights: [Int : CGFloat] = [:], cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil, addFeedback: Bool = true) -> InstantPageLayout {
public func instantPageLayoutForWebPage(_ webPage: TelegramMediaWebpage, instantPage: InstantPage?, userLocation: MediaResourceUserLocation, boundingWidth: CGFloat, sideInset: CGFloat, safeInset: CGFloat, strings: PresentationStrings, theme: InstantPageTheme, dateTimeFormat: PresentationDateTimeFormat, webEmbedHeights: [Int : CGFloat] = [:], cachedMessageSyntaxHighlight: CachedMessageSyntaxHighlight? = nil, addFeedback: Bool = true, fitToWidth: Bool = false) -> InstantPageLayout {
var maybeLoadedContent: TelegramMediaWebpageLoadedContent?
if case let .Loaded(content) = webPage.content {
maybeLoadedContent = content
@ -1084,8 +1089,8 @@ public func instantPageLayoutForWebPage(_ webPage: TelegramMediaWebpage, instant
var previousBlock: InstantPageBlock?
for i in 0 ..< pageBlocks.count {
let block = pageBlocks[i]
let blockLayout = layoutInstantPageBlock(webpage: webPage, userLocation: userLocation, rtl: rtl, block: block, boundingWidth: boundingWidth, horizontalInset: sideInset + safeInset, safeInset: safeInset, isCover: false, previousItems: items, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == pageBlocks.count - 1)
let spacing = spacingBetweenBlocks(upper: previousBlock, lower: block)
let blockLayout = layoutInstantPageBlock(webpage: webPage, userLocation: userLocation, rtl: rtl, block: block, boundingWidth: boundingWidth, horizontalInset: sideInset + safeInset, safeInset: safeInset, isCover: false, previousItems: items, fillToSize: nil, media: media, mediaIndexCounter: &mediaIndexCounter, embedIndexCounter: &embedIndexCounter, detailsIndexCounter: &detailsIndexCounter, theme: theme, strings: strings, dateTimeFormat: dateTimeFormat, webEmbedHeights: webEmbedHeights, cachedMessageSyntaxHighlight: cachedMessageSyntaxHighlight, excludeCaptions: false, isLast: i == pageBlocks.count - 1, fitToWidth: fitToWidth)
let spacing = spacingBetweenBlocks(upper: previousBlock, lower: block, fitToWidth: fitToWidth)
let blockItems = blockLayout.flattenedItemsWithOrigin(CGPoint(x: 0.0, y: contentSize.height + spacing))
items.append(contentsOf: blockItems)
if CGFloat(0.0).isLess(than: blockLayout.contentSize.height) {
@ -1094,7 +1099,7 @@ public func instantPageLayoutForWebPage(_ webPage: TelegramMediaWebpage, instant
}
}
let closingSpacing = spacingBetweenBlocks(upper: previousBlock, lower: nil)
let closingSpacing = spacingBetweenBlocks(upper: previousBlock, lower: nil, fitToWidth: fitToWidth)
contentSize.height += closingSpacing
if webPage.webpageId.id != 0 && addFeedback {
@ -1103,5 +1108,13 @@ public func instantPageLayoutForWebPage(_ webPage: TelegramMediaWebpage, instant
items.append(feedbackItem)
}
if fitToWidth {
contentSize.width = 0.0
for item in items {
contentSize.width = max(contentSize.width, ceil(item.frame.maxX) + sideInset)
}
contentSize.width = min(contentSize.width, boundingWidth)
}
return InstantPageLayout(origin: CGPoint(), contentSize: contentSize, items: items)
}

View file

@ -2,82 +2,114 @@ import Foundation
import UIKit
import TelegramCore
func spacingBetweenBlocks(upper: InstantPageBlock?, lower: InstantPageBlock?) -> CGFloat {
if let upper = upper, let lower = lower {
func spacingBetweenBlocks(upper: InstantPageBlock?, lower: InstantPageBlock?, fitToWidth: Bool) -> CGFloat {
if let upper, let lower {
switch (upper, lower) {
case (_, .cover), (_, .channelBanner), (.details, .details), (.relatedArticles, _), (_, .anchor):
return 0.0
case (.divider, _), (_, .divider):
case (_, .cover), (_, .channelBanner), (.details, .details), (.relatedArticles, _), (_, .anchor):
return 0.0
case (.divider, _), (_, .divider):
if fitToWidth {
return 10.0
} else {
return 25.0
case (_, .blockQuote), (.blockQuote, _), (_, .pullQuote), (.pullQuote, _):
return 27.0
case (.kicker, .title), (.cover, .title):
return 16.0
case (_, .title):
return 20.0
case (.title, .authorDate), (.subtitle, .authorDate):
return 18.0
case (_, .authorDate):
return 20.0
case (.title, .paragraph), (.authorDate, .paragraph):
return 34.0
case (.header, .paragraph), (.subheader, .paragraph), (.heading, .paragraph):
}
case (_, .blockQuote), (.blockQuote, _), (_, .pullQuote), (.pullQuote, _):
return 27.0
case (.kicker, .title), (.cover, .title):
return 16.0
case (_, .title):
return 20.0
case (.title, .authorDate), (.subtitle, .authorDate):
return 18.0
case (_, .authorDate):
return 20.0
case (.title, .paragraph), (.authorDate, .paragraph):
return 34.0
case (.header, .paragraph), (.subheader, .paragraph), (.heading, .paragraph):
if fitToWidth {
return 10.0
} else {
return 25.0
case (.list, .paragraph):
return 31.0
case (.preformatted, .paragraph):
return 19.0
case (.formula, .paragraph):
return 19.0
case (.paragraph, .paragraph):
}
case (.list, .paragraph):
return 31.0
case (.preformatted, .paragraph):
return 19.0
case (.formula, .paragraph):
return 19.0
case (.paragraph, .paragraph):
if fitToWidth {
return 10.0
} else {
return 25.0
case (_, .paragraph):
return 20.0
case (.title, .formula), (.authorDate, .formula):
return 34.0
case (.header, .formula), (.subheader, .formula), (.heading, .formula):
}
case (_, .paragraph):
return 20.0
case (.title, .formula), (.authorDate, .formula):
return 34.0
case (.header, .formula), (.subheader, .formula), (.heading, .formula):
if fitToWidth {
return 10.0
} else {
return 25.0
case (.list, .formula):
return 31.0
case (.preformatted, .formula):
return 19.0
case (.paragraph, .formula):
return 19.0
case (_, .formula):
return 20.0
case (.title, .list), (.authorDate, .list):
return 34.0
case (.header, .list), (.subheader, .list), (.heading, .list):
return 31.0
case (.preformatted, .list):
return 19.0
case (.formula, .list):
}
case (.list, .formula):
return 31.0
case (.preformatted, .formula):
return 19.0
case (.paragraph, .formula):
return 19.0
case (_, .formula):
return 20.0
case (.title, .list), (.authorDate, .list):
return 34.0
case (.header, .list), (.subheader, .list), (.heading, .list):
return 31.0
case (.preformatted, .list):
return 19.0
case (.formula, .list):
if fitToWidth {
return 10.0
} else {
return 25.0
case (_, .list):
}
case (_, .list):
if fitToWidth {
return 10.0
} else {
return 25.0
case (.paragraph, .preformatted):
return 19.0
case (.formula, .preformatted):
return 19.0
case (_, .preformatted):
return 20.0
case (_, .header), (_, .subheader), (_, .heading):
return 32.0
default:
return 20.0
}
case (.paragraph, .preformatted):
return 19.0
case (.formula, .preformatted):
return 19.0
case (_, .preformatted):
return 20.0
case (_, .header), (_, .subheader), (_, .heading):
return 32.0
default:
return 20.0
}
} else if let lower = lower {
} else if let lower {
switch lower {
case .cover, .channelBanner, .details, .anchor:
return 0.0
default:
case .cover, .channelBanner, .details, .anchor:
return 0.0
default:
if fitToWidth {
return 10.0
} else {
return 25.0
}
}
} else {
if let upper = upper, case .relatedArticles = upper {
return 0.0
} else {
return 25.0
if fitToWidth {
return 10.0
} else {
return 25.0
}
}
}
}

View file

@ -820,7 +820,7 @@ func attributedStringForRichText(_ text: RichText, styleStack: InstantPageTextSt
}
}
func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFloat, horizontalInset: CGFloat = 0.0, alignment: NSTextAlignment = .natural, offset: CGPoint, media: [EngineMedia.Id: EngineMedia] = [:], webpage: TelegramMediaWebpage? = nil, minimizeWidth: Bool = false, maxNumberOfLines: Int = 0, opaqueBackground: Bool = false) -> (InstantPageTextItem?, [InstantPageItem], CGSize) {
func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFloat, horizontalInset: CGFloat = 0.0, alignment: NSTextAlignment = .natural, offset: CGPoint, media: [EngineMedia.Id: EngineMedia] = [:], webpage: TelegramMediaWebpage? = nil, minimizeWidth: Bool = false, fitToWidth: Bool = false, maxNumberOfLines: Int = 0, opaqueBackground: Bool = false) -> (InstantPageTextItem?, [InstantPageItem], CGSize) {
if string.length == 0 {
return (nil, [], CGSize())
}
@ -1091,6 +1091,9 @@ func layoutTextItemWithString(_ string: NSAttributedString, boundingWidth: CGFlo
}
var textWidth = boundingWidth
if fitToWidth {
textWidth = maxLineWidth
}
var requiresScroll = false
if (!imageItems.isEmpty || !formulaItems.isEmpty) && maxLineWidth > boundingWidth + 10.0 {
textWidth = maxLineWidth

View file

@ -211,7 +211,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1605510357] = { return Api.ChatAdminRights.parse_chatAdminRights($0) }
dict[-219353309] = { return Api.ChatAdminWithInvites.parse_chatAdminWithInvites($0) }
dict[-1626209256] = { return Api.ChatBannedRights.parse_chatBannedRights($0) }
dict[-455036259] = { return Api.ChatFull.parse_channelFull($0) }
dict[-1605464774] = { return Api.ChatFull.parse_channelFull($0) }
dict[640893467] = { return Api.ChatFull.parse_chatFull($0) }
dict[1553807106] = { return Api.ChatInvite.parse_chatInvite($0) }
dict[1516793212] = { return Api.ChatInvite.parse_chatInviteAlready($0) }
@ -232,7 +232,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[878246344] = { return Api.ChatTheme.parse_chatThemeUniqueGift($0) }
dict[-1390068360] = { return Api.CodeSettings.parse_codeSettings($0) }
dict[-870702050] = { return Api.Config.parse_config($0) }
dict[-849058964] = { return Api.ConnectedBot.parse_connectedBot($0) }
dict[54448129] = { return Api.ConnectedBot.parse_connectedBot($0) }
dict[429997937] = { return Api.ConnectedBotStarRef.parse_connectedBotStarRef($0) }
dict[341499403] = { return Api.Contact.parse_contact($0) }
dict[496600883] = { return Api.ContactBirthday.parse_contactBirthday($0) }
@ -443,6 +443,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1548122514] = { return Api.InputNotifyPeer.parse_inputNotifyForumTopic($0) }
dict[-1195615476] = { return Api.InputNotifyPeer.parse_inputNotifyPeer($0) }
dict[423314455] = { return Api.InputNotifyPeer.parse_inputNotifyUsers($0) }
dict[2105227266] = { return Api.InputPageListOrderedItem.parse_inputPageListOrderedItemBlocks($0) }
dict[-1682665696] = { return Api.InputPageListOrderedItem.parse_inputPageListOrderedItemText($0) }
dict[1528613672] = { return Api.InputPasskeyCredential.parse_inputPasskeyCredentialFirebasePNV($0) }
dict[1009235855] = { return Api.InputPasskeyCredential.parse_inputPasskeyCredentialPublicKey($0) }
dict[-1021329078] = { return Api.InputPasskeyResponse.parse_inputPasskeyResponseLogin($0) }
@ -493,6 +495,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[1003796418] = { return Api.InputReplyTo.parse_inputReplyToMessage($0) }
dict[1775660101] = { return Api.InputReplyTo.parse_inputReplyToMonoForum($0) }
dict[1484862010] = { return Api.InputReplyTo.parse_inputReplyToStory($0) }
dict[-1865309654] = { return Api.InputRichMessage.parse_inputRichMessage($0) }
dict[-251549057] = { return Api.InputSavedStarGift.parse_inputSavedStarGiftChat($0) }
dict[545636920] = { return Api.InputSavedStarGift.parse_inputSavedStarGiftSlug($0) }
dict[1764202389] = { return Api.InputSavedStarGift.parse_inputSavedStarGiftUser($0) }
@ -548,6 +551,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[736157604] = { return Api.JSONValue.parse_jsonNumber($0) }
dict[-1715350371] = { return Api.JSONValue.parse_jsonObject($0) }
dict[-1222740358] = { return Api.JSONValue.parse_jsonString($0) }
dict[-1374344599] = { return Api.JoinChatBotResult.parse_joinChatBotResultApproved($0) }
dict[251265428] = { return Api.JoinChatBotResult.parse_joinChatBotResultDeclined($0) }
dict[-1734105024] = { return Api.JoinChatBotResult.parse_joinChatBotResultQueued($0) }
dict[-689719277] = { return Api.JoinChatBotResult.parse_joinChatBotResultWebView($0) }
dict[45580630] = { return Api.KeyboardButton.parse_inputKeyboardButtonRequestPeer($0) }
dict[1744911986] = { return Api.KeyboardButton.parse_inputKeyboardButtonUrlAuth($0) }
dict[2103314375] = { return Api.KeyboardButton.parse_inputKeyboardButtonUserProfile($0) }
@ -585,7 +592,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1098720356] = { return Api.MediaArea.parse_mediaAreaVenue($0) }
dict[1235637404] = { return Api.MediaArea.parse_mediaAreaWeather($0) }
dict[-808853502] = { return Api.MediaAreaCoordinates.parse_mediaAreaCoordinates($0) }
dict[-1779470549] = { return Api.Message.parse_message($0) }
dict[1979759059] = { return Api.Message.parse_message($0) }
dict[-1868117372] = { return Api.Message.parse_messageEmpty($0) }
dict[2055212554] = { return Api.Message.parse_messageService($0) }
dict[-872240531] = { return Api.MessageAction.parse_messageActionBoostApply($0) }
@ -746,6 +753,11 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1261946036] = { return Api.NotifyPeer.parse_notifyUsers($0) }
dict[1001931436] = { return Api.OutboxReadDate.parse_outboxReadDate($0) }
dict[-1738178803] = { return Api.Page.parse_page($0) }
dict[-1715334046] = { return Api.PageBlock.parse_inputPageBlockAudio($0) }
dict[1464557951] = { return Api.PageBlock.parse_inputPageBlockMap($0) }
dict[-1186155733] = { return Api.PageBlock.parse_inputPageBlockOrderedList($0) }
dict[719646565] = { return Api.PageBlock.parse_inputPageBlockPhoto($0) }
dict[-249943466] = { return Api.PageBlock.parse_inputPageBlockVideo($0) }
dict[-837994576] = { return Api.PageBlock.parse_pageBlockAnchor($0) }
dict[-2143067670] = { return Api.PageBlock.parse_pageBlockAudio($0) }
dict[-1162877472] = { return Api.PageBlock.parse_pageBlockAuthorDate($0) }
@ -759,9 +771,16 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-229005301] = { return Api.PageBlock.parse_pageBlockEmbedPost($0) }
dict[1216809369] = { return Api.PageBlock.parse_pageBlockFooter($0) }
dict[-1076861716] = { return Api.PageBlock.parse_pageBlockHeader($0) }
dict[-1157691601] = { return Api.PageBlock.parse_pageBlockHeading1($0) }
dict[158018284] = { return Api.PageBlock.parse_pageBlockHeading2($0) }
dict[1743204781] = { return Api.PageBlock.parse_pageBlockHeading3($0) }
dict[-1254983893] = { return Api.PageBlock.parse_pageBlockHeading4($0) }
dict[-608277398] = { return Api.PageBlock.parse_pageBlockHeading5($0) }
dict[1747599785] = { return Api.PageBlock.parse_pageBlockHeading6($0) }
dict[504660880] = { return Api.PageBlock.parse_pageBlockKicker($0) }
dict[-454524911] = { return Api.PageBlock.parse_pageBlockList($0) }
dict[-1538310410] = { return Api.PageBlock.parse_pageBlockMap($0) }
dict[1493699616] = { return Api.PageBlock.parse_pageBlockMath($0) }
dict[-1702174239] = { return Api.PageBlock.parse_pageBlockOrderedList($0) }
dict[1182402406] = { return Api.PageBlock.parse_pageBlockParagraph($0) }
dict[391759200] = { return Api.PageBlock.parse_pageBlockPhoto($0) }
@ -776,10 +795,10 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[324435594] = { return Api.PageBlock.parse_pageBlockUnsupported($0) }
dict[2089805750] = { return Api.PageBlock.parse_pageBlockVideo($0) }
dict[1869903447] = { return Api.PageCaption.parse_pageCaption($0) }
dict[635466748] = { return Api.PageListItem.parse_pageListItemBlocks($0) }
dict[-1188055347] = { return Api.PageListItem.parse_pageListItemText($0) }
dict[-1730311882] = { return Api.PageListOrderedItem.parse_pageListOrderedItemBlocks($0) }
dict[1577484359] = { return Api.PageListOrderedItem.parse_pageListOrderedItemText($0) }
dict[1674209194] = { return Api.PageListItem.parse_pageListItemBlocks($0) }
dict[794323004] = { return Api.PageListItem.parse_pageListItemText($0) }
dict[1109995988] = { return Api.PageListOrderedItem.parse_pageListOrderedItemBlocks($0) }
dict[-851533770] = { return Api.PageListOrderedItem.parse_pageListOrderedItemText($0) }
dict[-1282352120] = { return Api.PageRelatedArticle.parse_pageRelatedArticle($0) }
dict[878078826] = { return Api.PageTableCell.parse_pageTableCell($0) }
dict[-524237339] = { return Api.PageTableRow.parse_pageTableRow($0) }
@ -922,15 +941,19 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1258914157] = { return Api.RequirementToContact.parse_requirementToContactPaidMessages($0) }
dict[-444472087] = { return Api.RequirementToContact.parse_requirementToContactPremium($0) }
dict[-797791052] = { return Api.RestrictionReason.parse_restrictionReason($0) }
dict[-1158439541] = { return Api.RichMessage.parse_richMessage($0) }
dict[764156522] = { return Api.RichText.parse_inputTextImage($0) }
dict[894777186] = { return Api.RichText.parse_textAnchor($0) }
dict[1730456516] = { return Api.RichText.parse_textBold($0) }
dict[2120376535] = { return Api.RichText.parse_textConcat($0) }
dict[-1570679104] = { return Api.RichText.parse_textCustomEmoji($0) }
dict[-564523562] = { return Api.RichText.parse_textEmail($0) }
dict[-599948721] = { return Api.RichText.parse_textEmpty($0) }
dict[1816074681] = { return Api.RichText.parse_textFixed($0) }
dict[136105807] = { return Api.RichText.parse_textImage($0) }
dict[-653089380] = { return Api.RichText.parse_textItalic($0) }
dict[55281185] = { return Api.RichText.parse_textMarked($0) }
dict[-1657885545] = { return Api.RichText.parse_textMath($0) }
dict[483104362] = { return Api.RichText.parse_textPhone($0) }
dict[1950782688] = { return Api.RichText.parse_textPlain($0) }
dict[-1678197867] = { return Api.RichText.parse_textStrike($0) }
@ -1109,7 +1132,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1964652166] = { return Api.Update.parse_updateBotBusinessConnect($0) }
dict[-1177566067] = { return Api.Update.parse_updateBotCallbackQuery($0) }
dict[-1873947492] = { return Api.Update.parse_updateBotChatBoost($0) }
dict[299870598] = { return Api.Update.parse_updateBotChatInviteRequester($0) }
dict[2092125561] = { return Api.Update.parse_updateBotChatInviteRequester($0) }
dict[1299263278] = { return Api.Update.parse_updateBotCommands($0) }
dict[-1607821266] = { return Api.Update.parse_updateBotDeleteBusinessMessage($0) }
dict[132077692] = { return Api.Update.parse_updateBotEditBusinessMessage($0) }
@ -1177,6 +1200,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-667783411] = { return Api.Update.parse_updateGroupCallMessage($0) }
dict[-219423922] = { return Api.Update.parse_updateGroupCallParticipants($0) }
dict[1763610706] = { return Api.Update.parse_updateInlineBotCallbackQuery($0) }
dict[-1112768912] = { return Api.Update.parse_updateJoinChatWebViewDecision($0) }
dict[1442983757] = { return Api.Update.parse_updateLangPack($0) }
dict[1180041828] = { return Api.Update.parse_updateLangPackTooLong($0) }
dict[1448076945] = { return Api.Update.parse_updateLoginToken($0) }
@ -1189,6 +1213,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1618924792] = { return Api.Update.parse_updateMonoForumNoPaidException($0) }
dict[-2030252155] = { return Api.Update.parse_updateMoveStickerSetToTop($0) }
dict[-1991136273] = { return Api.Update.parse_updateNewAuthorization($0) }
dict[-1306491994] = { return Api.Update.parse_updateNewBotConnection($0) }
dict[1656358105] = { return Api.Update.parse_updateNewChannelMessage($0) }
dict[314359194] = { return Api.Update.parse_updateNewEncryptedMessage($0) }
dict[522914557] = { return Api.Update.parse_updateNewMessage($0) }
@ -1257,6 +1282,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[88680979] = { return Api.Update.parse_updateUserPhone($0) }
dict[-440534818] = { return Api.Update.parse_updateUserStatus($0) }
dict[706199388] = { return Api.Update.parse_updateUserTyping($0) }
dict[335872721] = { return Api.Update.parse_updateWebBrowserException($0) }
dict[-1013306658] = { return Api.Update.parse_updateWebBrowserSettings($0) }
dict[2139689491] = { return Api.Update.parse_updateWebPage($0) }
dict[361936797] = { return Api.Update.parse_updateWebViewResultSent($0) }
dict[2027216577] = { return Api.Updates.parse_updateShort($0) }
@ -1290,6 +1317,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1493633966] = { return Api.WebAuthorization.parse_webAuthorization($0) }
dict[475467473] = { return Api.WebDocument.parse_webDocument($0) }
dict[-104284986] = { return Api.WebDocument.parse_webDocumentNoProxy($0) }
dict[-1824741993] = { return Api.WebDomainException.parse_webDomainException($0) }
dict[-392411726] = { return Api.WebPage.parse_webPage($0) }
dict[555358088] = { return Api.WebPage.parse_webPageEmpty($0) }
dict[1930545681] = { return Api.WebPage.parse_webPageNotModified($0) }
@ -1341,6 +1369,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-842824308] = { return Api.account.WallPapers.parse_wallPapers($0) }
dict[471437699] = { return Api.account.WallPapers.parse_wallPapersNotModified($0) }
dict[-313079300] = { return Api.account.WebAuthorizations.parse_webAuthorizations($0) }
dict[2045480115] = { return Api.account.WebBrowserSettings.parse_webBrowserSettings($0) }
dict[-1021538482] = { return Api.account.WebBrowserSettings.parse_webBrowserSettingsNotModified($0) }
dict[1822232318] = { return Api.aicompose.Tones.parse_tones($0) }
dict[-1040948989] = { return Api.aicompose.Tones.parse_tonesNotModified($0) }
dict[782418132] = { return Api.auth.Authorization.parse_authorization($0) }
@ -1452,6 +1482,8 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
dict[-1231326505] = { return Api.messages.ChatAdminsWithInvites.parse_chatAdminsWithInvites($0) }
dict[-438840932] = { return Api.messages.ChatFull.parse_chatFull($0) }
dict[-2118733814] = { return Api.messages.ChatInviteImporters.parse_chatInviteImporters($0) }
dict[1146512295] = { return Api.messages.ChatInviteJoinResult.parse_chatInviteJoinResultOk($0) }
dict[2001452532] = { return Api.messages.ChatInviteJoinResult.parse_chatInviteJoinResultWebView($0) }
dict[1694474197] = { return Api.messages.Chats.parse_chats($0) }
dict[-1663561404] = { return Api.messages.Chats.parse_chatsSlice($0) }
dict[-1571952873] = { return Api.messages.CheckedHistoryImportPeer.parse_checkedHistoryImportPeer($0) }
@ -1998,6 +2030,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.InputNotifyPeer:
_1.serialize(buffer, boxed)
case let _1 as Api.InputPageListOrderedItem:
_1.serialize(buffer, boxed)
case let _1 as Api.InputPasskeyCredential:
_1.serialize(buffer, boxed)
case let _1 as Api.InputPasskeyResponse:
@ -2020,6 +2054,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.InputReplyTo:
_1.serialize(buffer, boxed)
case let _1 as Api.InputRichMessage:
_1.serialize(buffer, boxed)
case let _1 as Api.InputSavedStarGift:
_1.serialize(buffer, boxed)
case let _1 as Api.InputSecureFile:
@ -2058,6 +2094,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.JSONValue:
_1.serialize(buffer, boxed)
case let _1 as Api.JoinChatBotResult:
_1.serialize(buffer, boxed)
case let _1 as Api.KeyboardButton:
_1.serialize(buffer, boxed)
case let _1 as Api.KeyboardButtonRow:
@ -2240,6 +2278,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.RestrictionReason:
_1.serialize(buffer, boxed)
case let _1 as Api.RichMessage:
_1.serialize(buffer, boxed)
case let _1 as Api.RichText:
_1.serialize(buffer, boxed)
case let _1 as Api.SavedContact:
@ -2428,6 +2468,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.WebDocument:
_1.serialize(buffer, boxed)
case let _1 as Api.WebDomainException:
_1.serialize(buffer, boxed)
case let _1 as Api.WebPage:
_1.serialize(buffer, boxed)
case let _1 as Api.WebPageAttribute:
@ -2492,6 +2534,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.account.WebAuthorizations:
_1.serialize(buffer, boxed)
case let _1 as Api.account.WebBrowserSettings:
_1.serialize(buffer, boxed)
case let _1 as Api.aicompose.Tones:
_1.serialize(buffer, boxed)
case let _1 as Api.auth.Authorization:
@ -2628,6 +2672,8 @@ public extension Api {
_1.serialize(buffer, boxed)
case let _1 as Api.messages.ChatInviteImporters:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.ChatInviteJoinResult:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.Chats:
_1.serialize(buffer, boxed)
case let _1 as Api.messages.CheckedHistoryImportPeer:

View file

@ -1451,85 +1451,131 @@ public extension Api {
}
}
public extension Api {
enum InputPasskeyCredential: TypeConstructorDescription {
public class Cons_inputPasskeyCredentialFirebasePNV: TypeConstructorDescription {
public var pnvToken: String
public init(pnvToken: String) {
self.pnvToken = pnvToken
indirect enum InputPageListOrderedItem: TypeConstructorDescription {
public class Cons_inputPageListOrderedItemBlocks: TypeConstructorDescription {
public var flags: Int32
public var blocks: [Api.PageBlock]
public var value: Int32?
public var type: String?
public init(flags: Int32, blocks: [Api.PageBlock], value: Int32?, type: String?) {
self.flags = flags
self.blocks = blocks
self.value = value
self.type = type
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPasskeyCredentialFirebasePNV", [("pnvToken", ConstructorParameterDescription(self.pnvToken))])
return ("inputPageListOrderedItemBlocks", [("flags", ConstructorParameterDescription(self.flags)), ("blocks", ConstructorParameterDescription(self.blocks)), ("value", ConstructorParameterDescription(self.value)), ("type", ConstructorParameterDescription(self.type))])
}
}
public class Cons_inputPasskeyCredentialPublicKey: TypeConstructorDescription {
public var id: String
public var rawId: String
public var response: Api.InputPasskeyResponse
public init(id: String, rawId: String, response: Api.InputPasskeyResponse) {
self.id = id
self.rawId = rawId
self.response = response
public class Cons_inputPageListOrderedItemText: TypeConstructorDescription {
public var flags: Int32
public var text: Api.RichText
public var value: Int32?
public var type: String?
public init(flags: Int32, text: Api.RichText, value: Int32?, type: String?) {
self.flags = flags
self.text = text
self.value = value
self.type = type
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPasskeyCredentialPublicKey", [("id", ConstructorParameterDescription(self.id)), ("rawId", ConstructorParameterDescription(self.rawId)), ("response", ConstructorParameterDescription(self.response))])
return ("inputPageListOrderedItemText", [("flags", ConstructorParameterDescription(self.flags)), ("text", ConstructorParameterDescription(self.text)), ("value", ConstructorParameterDescription(self.value)), ("type", ConstructorParameterDescription(self.type))])
}
}
case inputPasskeyCredentialFirebasePNV(Cons_inputPasskeyCredentialFirebasePNV)
case inputPasskeyCredentialPublicKey(Cons_inputPasskeyCredentialPublicKey)
case inputPageListOrderedItemBlocks(Cons_inputPageListOrderedItemBlocks)
case inputPageListOrderedItemText(Cons_inputPageListOrderedItemText)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPasskeyCredentialFirebasePNV(let _data):
case .inputPageListOrderedItemBlocks(let _data):
if boxed {
buffer.appendInt32(1528613672)
buffer.appendInt32(2105227266)
}
serializeInt32(_data.flags, buffer: buffer, boxed: false)
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(_data.blocks.count))
for item in _data.blocks {
item.serialize(buffer, true)
}
if Int(_data.flags) & Int(1 << 2) != 0 {
serializeInt32(_data.value!, buffer: buffer, boxed: false)
}
if Int(_data.flags) & Int(1 << 3) != 0 {
serializeString(_data.type!, buffer: buffer, boxed: false)
}
serializeString(_data.pnvToken, buffer: buffer, boxed: false)
break
case .inputPasskeyCredentialPublicKey(let _data):
case .inputPageListOrderedItemText(let _data):
if boxed {
buffer.appendInt32(1009235855)
buffer.appendInt32(-1682665696)
}
serializeInt32(_data.flags, buffer: buffer, boxed: false)
_data.text.serialize(buffer, true)
if Int(_data.flags) & Int(1 << 2) != 0 {
serializeInt32(_data.value!, buffer: buffer, boxed: false)
}
if Int(_data.flags) & Int(1 << 3) != 0 {
serializeString(_data.type!, buffer: buffer, boxed: false)
}
serializeString(_data.id, buffer: buffer, boxed: false)
serializeString(_data.rawId, buffer: buffer, boxed: false)
_data.response.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
switch self {
case .inputPasskeyCredentialFirebasePNV(let _data):
return ("inputPasskeyCredentialFirebasePNV", [("pnvToken", ConstructorParameterDescription(_data.pnvToken))])
case .inputPasskeyCredentialPublicKey(let _data):
return ("inputPasskeyCredentialPublicKey", [("id", ConstructorParameterDescription(_data.id)), ("rawId", ConstructorParameterDescription(_data.rawId)), ("response", ConstructorParameterDescription(_data.response))])
case .inputPageListOrderedItemBlocks(let _data):
return ("inputPageListOrderedItemBlocks", [("flags", ConstructorParameterDescription(_data.flags)), ("blocks", ConstructorParameterDescription(_data.blocks)), ("value", ConstructorParameterDescription(_data.value)), ("type", ConstructorParameterDescription(_data.type))])
case .inputPageListOrderedItemText(let _data):
return ("inputPageListOrderedItemText", [("flags", ConstructorParameterDescription(_data.flags)), ("text", ConstructorParameterDescription(_data.text)), ("value", ConstructorParameterDescription(_data.value)), ("type", ConstructorParameterDescription(_data.type))])
}
}
public static func parse_inputPasskeyCredentialFirebasePNV(_ reader: BufferReader) -> InputPasskeyCredential? {
var _1: String?
_1 = parseString(reader)
public static func parse_inputPageListOrderedItemBlocks(_ reader: BufferReader) -> InputPageListOrderedItem? {
var _1: Int32?
_1 = reader.readInt32()
var _2: [Api.PageBlock]?
if let _ = reader.readInt32() {
_2 = Api.parseVector(reader, elementSignature: 0, elementType: Api.PageBlock.self)
}
var _3: Int32?
if Int(_1 ?? 0) & Int(1 << 2) != 0 {
_3 = reader.readInt32()
}
var _4: String?
if Int(_1 ?? 0) & Int(1 << 3) != 0 {
_4 = parseString(reader)
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPasskeyCredential.inputPasskeyCredentialFirebasePNV(Cons_inputPasskeyCredentialFirebasePNV(pnvToken: _1!))
let _c2 = _2 != nil
let _c3 = (Int(_1 ?? 0) & Int(1 << 2) == 0) || _3 != nil
let _c4 = (Int(_1 ?? 0) & Int(1 << 3) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputPageListOrderedItem.inputPageListOrderedItemBlocks(Cons_inputPageListOrderedItemBlocks(flags: _1!, blocks: _2!, value: _3, type: _4))
}
else {
return nil
}
}
public static func parse_inputPasskeyCredentialPublicKey(_ reader: BufferReader) -> InputPasskeyCredential? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
var _3: Api.InputPasskeyResponse?
public static func parse_inputPageListOrderedItemText(_ reader: BufferReader) -> InputPageListOrderedItem? {
var _1: Int32?
_1 = reader.readInt32()
var _2: Api.RichText?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.InputPasskeyResponse
_2 = Api.parse(reader, signature: signature) as? Api.RichText
}
var _3: Int32?
if Int(_1 ?? 0) & Int(1 << 2) != 0 {
_3 = reader.readInt32()
}
var _4: String?
if Int(_1 ?? 0) & Int(1 << 3) != 0 {
_4 = parseString(reader)
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputPasskeyCredential.inputPasskeyCredentialPublicKey(Cons_inputPasskeyCredentialPublicKey(id: _1!, rawId: _2!, response: _3!))
let _c3 = (Int(_1 ?? 0) & Int(1 << 2) == 0) || _3 != nil
let _c4 = (Int(_1 ?? 0) & Int(1 << 3) == 0) || _4 != nil
if _c1 && _c2 && _c3 && _c4 {
return Api.InputPageListOrderedItem.inputPageListOrderedItemText(Cons_inputPageListOrderedItemText(flags: _1!, text: _2!, value: _3, type: _4))
}
else {
return nil

View file

@ -1,3 +1,90 @@
public extension Api {
enum InputPasskeyCredential: TypeConstructorDescription {
public class Cons_inputPasskeyCredentialFirebasePNV: TypeConstructorDescription {
public var pnvToken: String
public init(pnvToken: String) {
self.pnvToken = pnvToken
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPasskeyCredentialFirebasePNV", [("pnvToken", ConstructorParameterDescription(self.pnvToken))])
}
}
public class Cons_inputPasskeyCredentialPublicKey: TypeConstructorDescription {
public var id: String
public var rawId: String
public var response: Api.InputPasskeyResponse
public init(id: String, rawId: String, response: Api.InputPasskeyResponse) {
self.id = id
self.rawId = rawId
self.response = response
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPasskeyCredentialPublicKey", [("id", ConstructorParameterDescription(self.id)), ("rawId", ConstructorParameterDescription(self.rawId)), ("response", ConstructorParameterDescription(self.response))])
}
}
case inputPasskeyCredentialFirebasePNV(Cons_inputPasskeyCredentialFirebasePNV)
case inputPasskeyCredentialPublicKey(Cons_inputPasskeyCredentialPublicKey)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPasskeyCredentialFirebasePNV(let _data):
if boxed {
buffer.appendInt32(1528613672)
}
serializeString(_data.pnvToken, buffer: buffer, boxed: false)
break
case .inputPasskeyCredentialPublicKey(let _data):
if boxed {
buffer.appendInt32(1009235855)
}
serializeString(_data.id, buffer: buffer, boxed: false)
serializeString(_data.rawId, buffer: buffer, boxed: false)
_data.response.serialize(buffer, true)
break
}
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
switch self {
case .inputPasskeyCredentialFirebasePNV(let _data):
return ("inputPasskeyCredentialFirebasePNV", [("pnvToken", ConstructorParameterDescription(_data.pnvToken))])
case .inputPasskeyCredentialPublicKey(let _data):
return ("inputPasskeyCredentialPublicKey", [("id", ConstructorParameterDescription(_data.id)), ("rawId", ConstructorParameterDescription(_data.rawId)), ("response", ConstructorParameterDescription(_data.response))])
}
}
public static func parse_inputPasskeyCredentialFirebasePNV(_ reader: BufferReader) -> InputPasskeyCredential? {
var _1: String?
_1 = parseString(reader)
let _c1 = _1 != nil
if _c1 {
return Api.InputPasskeyCredential.inputPasskeyCredentialFirebasePNV(Cons_inputPasskeyCredentialFirebasePNV(pnvToken: _1!))
}
else {
return nil
}
}
public static func parse_inputPasskeyCredentialPublicKey(_ reader: BufferReader) -> InputPasskeyCredential? {
var _1: String?
_1 = parseString(reader)
var _2: String?
_2 = parseString(reader)
var _3: Api.InputPasskeyResponse?
if let signature = reader.readInt32() {
_3 = Api.parse(reader, signature: signature) as? Api.InputPasskeyResponse
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
if _c1 && _c2 && _c3 {
return Api.InputPasskeyCredential.inputPasskeyCredentialPublicKey(Cons_inputPasskeyCredentialPublicKey(id: _1!, rawId: _2!, response: _3!))
}
else {
return nil
}
}
}
}
public extension Api {
enum InputPasskeyResponse: TypeConstructorDescription {
public class Cons_inputPasskeyResponseLogin: TypeConstructorDescription {
@ -882,246 +969,3 @@ public extension Api {
}
}
}
public extension Api {
enum InputPrivacyRule: TypeConstructorDescription {
public class Cons_inputPrivacyValueAllowChatParticipants: TypeConstructorDescription {
public var chats: [Int64]
public init(chats: [Int64]) {
self.chats = chats
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPrivacyValueAllowChatParticipants", [("chats", ConstructorParameterDescription(self.chats))])
}
}
public class Cons_inputPrivacyValueAllowUsers: TypeConstructorDescription {
public var users: [Api.InputUser]
public init(users: [Api.InputUser]) {
self.users = users
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPrivacyValueAllowUsers", [("users", ConstructorParameterDescription(self.users))])
}
}
public class Cons_inputPrivacyValueDisallowChatParticipants: TypeConstructorDescription {
public var chats: [Int64]
public init(chats: [Int64]) {
self.chats = chats
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPrivacyValueDisallowChatParticipants", [("chats", ConstructorParameterDescription(self.chats))])
}
}
public class Cons_inputPrivacyValueDisallowUsers: TypeConstructorDescription {
public var users: [Api.InputUser]
public init(users: [Api.InputUser]) {
self.users = users
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("inputPrivacyValueDisallowUsers", [("users", ConstructorParameterDescription(self.users))])
}
}
case inputPrivacyValueAllowAll
case inputPrivacyValueAllowBots
case inputPrivacyValueAllowChatParticipants(Cons_inputPrivacyValueAllowChatParticipants)
case inputPrivacyValueAllowCloseFriends
case inputPrivacyValueAllowContacts
case inputPrivacyValueAllowPremium
case inputPrivacyValueAllowUsers(Cons_inputPrivacyValueAllowUsers)
case inputPrivacyValueDisallowAll
case inputPrivacyValueDisallowBots
case inputPrivacyValueDisallowChatParticipants(Cons_inputPrivacyValueDisallowChatParticipants)
case inputPrivacyValueDisallowContacts
case inputPrivacyValueDisallowUsers(Cons_inputPrivacyValueDisallowUsers)
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
switch self {
case .inputPrivacyValueAllowAll:
if boxed {
buffer.appendInt32(407582158)
}
break
case .inputPrivacyValueAllowBots:
if boxed {
buffer.appendInt32(1515179237)
}
break
case .inputPrivacyValueAllowChatParticipants(let _data):
if boxed {
buffer.appendInt32(-2079962673)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(_data.chats.count))
for item in _data.chats {
serializeInt64(item, buffer: buffer, boxed: false)
}
break
case .inputPrivacyValueAllowCloseFriends:
if boxed {
buffer.appendInt32(793067081)
}
break
case .inputPrivacyValueAllowContacts:
if boxed {
buffer.appendInt32(218751099)
}
break
case .inputPrivacyValueAllowPremium:
if boxed {
buffer.appendInt32(2009975281)
}
break
case .inputPrivacyValueAllowUsers(let _data):
if boxed {
buffer.appendInt32(320652927)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(_data.users.count))
for item in _data.users {
item.serialize(buffer, true)
}
break
case .inputPrivacyValueDisallowAll:
if boxed {
buffer.appendInt32(-697604407)
}
break
case .inputPrivacyValueDisallowBots:
if boxed {
buffer.appendInt32(-991594219)
}
break
case .inputPrivacyValueDisallowChatParticipants(let _data):
if boxed {
buffer.appendInt32(-380694650)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(_data.chats.count))
for item in _data.chats {
serializeInt64(item, buffer: buffer, boxed: false)
}
break
case .inputPrivacyValueDisallowContacts:
if boxed {
buffer.appendInt32(195371015)
}
break
case .inputPrivacyValueDisallowUsers(let _data):
if boxed {
buffer.appendInt32(-1877932953)
}
buffer.appendInt32(481674261)
buffer.appendInt32(Int32(_data.users.count))
for item in _data.users {
item.serialize(buffer, true)
}
break
}
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
switch self {
case .inputPrivacyValueAllowAll:
return ("inputPrivacyValueAllowAll", [])
case .inputPrivacyValueAllowBots:
return ("inputPrivacyValueAllowBots", [])
case .inputPrivacyValueAllowChatParticipants(let _data):
return ("inputPrivacyValueAllowChatParticipants", [("chats", ConstructorParameterDescription(_data.chats))])
case .inputPrivacyValueAllowCloseFriends:
return ("inputPrivacyValueAllowCloseFriends", [])
case .inputPrivacyValueAllowContacts:
return ("inputPrivacyValueAllowContacts", [])
case .inputPrivacyValueAllowPremium:
return ("inputPrivacyValueAllowPremium", [])
case .inputPrivacyValueAllowUsers(let _data):
return ("inputPrivacyValueAllowUsers", [("users", ConstructorParameterDescription(_data.users))])
case .inputPrivacyValueDisallowAll:
return ("inputPrivacyValueDisallowAll", [])
case .inputPrivacyValueDisallowBots:
return ("inputPrivacyValueDisallowBots", [])
case .inputPrivacyValueDisallowChatParticipants(let _data):
return ("inputPrivacyValueDisallowChatParticipants", [("chats", ConstructorParameterDescription(_data.chats))])
case .inputPrivacyValueDisallowContacts:
return ("inputPrivacyValueDisallowContacts", [])
case .inputPrivacyValueDisallowUsers(let _data):
return ("inputPrivacyValueDisallowUsers", [("users", ConstructorParameterDescription(_data.users))])
}
}
public static func parse_inputPrivacyValueAllowAll(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueAllowAll
}
public static func parse_inputPrivacyValueAllowBots(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueAllowBots
}
public static func parse_inputPrivacyValueAllowChatParticipants(_ reader: BufferReader) -> InputPrivacyRule? {
var _1: [Int64]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPrivacyRule.inputPrivacyValueAllowChatParticipants(Cons_inputPrivacyValueAllowChatParticipants(chats: _1!))
}
else {
return nil
}
}
public static func parse_inputPrivacyValueAllowCloseFriends(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueAllowCloseFriends
}
public static func parse_inputPrivacyValueAllowContacts(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueAllowContacts
}
public static func parse_inputPrivacyValueAllowPremium(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueAllowPremium
}
public static func parse_inputPrivacyValueAllowUsers(_ reader: BufferReader) -> InputPrivacyRule? {
var _1: [Api.InputUser]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputUser.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPrivacyRule.inputPrivacyValueAllowUsers(Cons_inputPrivacyValueAllowUsers(users: _1!))
}
else {
return nil
}
}
public static func parse_inputPrivacyValueDisallowAll(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueDisallowAll
}
public static func parse_inputPrivacyValueDisallowBots(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueDisallowBots
}
public static func parse_inputPrivacyValueDisallowChatParticipants(_ reader: BufferReader) -> InputPrivacyRule? {
var _1: [Int64]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 570911930, elementType: Int64.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPrivacyRule.inputPrivacyValueDisallowChatParticipants(Cons_inputPrivacyValueDisallowChatParticipants(chats: _1!))
}
else {
return nil
}
}
public static func parse_inputPrivacyValueDisallowContacts(_ reader: BufferReader) -> InputPrivacyRule? {
return Api.InputPrivacyRule.inputPrivacyValueDisallowContacts
}
public static func parse_inputPrivacyValueDisallowUsers(_ reader: BufferReader) -> InputPrivacyRule? {
var _1: [Api.InputUser]?
if let _ = reader.readInt32() {
_1 = Api.parseVector(reader, elementSignature: 0, elementType: Api.InputUser.self)
}
let _c1 = _1 != nil
if _c1 {
return Api.InputPrivacyRule.inputPrivacyValueDisallowUsers(Cons_inputPrivacyValueDisallowUsers(users: _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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1450,7 +1450,8 @@ public extension Api {
public var stargiftsCount: Int32?
public var sendPaidMessagesStars: Int64?
public var mainTab: Api.ProfileTab?
public init(flags: Int32, flags2: Int32, id: Int64, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int64?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int64?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, defaultSendAs: Api.Peer?, availableReactions: Api.ChatReactions?, reactionsLimit: Int32?, stories: Api.PeerStories?, wallpaper: Api.WallPaper?, boostsApplied: Int32?, boostsUnrestrict: Int32?, emojiset: Api.StickerSet?, botVerification: Api.BotVerification?, stargiftsCount: Int32?, sendPaidMessagesStars: Int64?, mainTab: Api.ProfileTab?) {
public var guardBotId: Int64?
public init(flags: Int32, flags2: Int32, id: Int64, about: String, participantsCount: Int32?, adminsCount: Int32?, kickedCount: Int32?, bannedCount: Int32?, onlineCount: Int32?, readInboxMaxId: Int32, readOutboxMaxId: Int32, unreadCount: Int32, chatPhoto: Api.Photo, notifySettings: Api.PeerNotifySettings, exportedInvite: Api.ExportedChatInvite?, botInfo: [Api.BotInfo], migratedFromChatId: Int64?, migratedFromMaxId: Int32?, pinnedMsgId: Int32?, stickerset: Api.StickerSet?, availableMinId: Int32?, folderId: Int32?, linkedChatId: Int64?, location: Api.ChannelLocation?, slowmodeSeconds: Int32?, slowmodeNextSendDate: Int32?, statsDc: Int32?, pts: Int32, call: Api.InputGroupCall?, ttlPeriod: Int32?, pendingSuggestions: [String]?, groupcallDefaultJoinAs: Api.Peer?, themeEmoticon: String?, requestsPending: Int32?, recentRequesters: [Int64]?, defaultSendAs: Api.Peer?, availableReactions: Api.ChatReactions?, reactionsLimit: Int32?, stories: Api.PeerStories?, wallpaper: Api.WallPaper?, boostsApplied: Int32?, boostsUnrestrict: Int32?, emojiset: Api.StickerSet?, botVerification: Api.BotVerification?, stargiftsCount: Int32?, sendPaidMessagesStars: Int64?, mainTab: Api.ProfileTab?, guardBotId: Int64?) {
self.flags = flags
self.flags2 = flags2
self.id = id
@ -1498,9 +1499,10 @@ public extension Api {
self.stargiftsCount = stargiftsCount
self.sendPaidMessagesStars = sendPaidMessagesStars
self.mainTab = mainTab
self.guardBotId = guardBotId
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("channelFull", [("flags", ConstructorParameterDescription(self.flags)), ("flags2", ConstructorParameterDescription(self.flags2)), ("id", ConstructorParameterDescription(self.id)), ("about", ConstructorParameterDescription(self.about)), ("participantsCount", ConstructorParameterDescription(self.participantsCount)), ("adminsCount", ConstructorParameterDescription(self.adminsCount)), ("kickedCount", ConstructorParameterDescription(self.kickedCount)), ("bannedCount", ConstructorParameterDescription(self.bannedCount)), ("onlineCount", ConstructorParameterDescription(self.onlineCount)), ("readInboxMaxId", ConstructorParameterDescription(self.readInboxMaxId)), ("readOutboxMaxId", ConstructorParameterDescription(self.readOutboxMaxId)), ("unreadCount", ConstructorParameterDescription(self.unreadCount)), ("chatPhoto", ConstructorParameterDescription(self.chatPhoto)), ("notifySettings", ConstructorParameterDescription(self.notifySettings)), ("exportedInvite", ConstructorParameterDescription(self.exportedInvite)), ("botInfo", ConstructorParameterDescription(self.botInfo)), ("migratedFromChatId", ConstructorParameterDescription(self.migratedFromChatId)), ("migratedFromMaxId", ConstructorParameterDescription(self.migratedFromMaxId)), ("pinnedMsgId", ConstructorParameterDescription(self.pinnedMsgId)), ("stickerset", ConstructorParameterDescription(self.stickerset)), ("availableMinId", ConstructorParameterDescription(self.availableMinId)), ("folderId", ConstructorParameterDescription(self.folderId)), ("linkedChatId", ConstructorParameterDescription(self.linkedChatId)), ("location", ConstructorParameterDescription(self.location)), ("slowmodeSeconds", ConstructorParameterDescription(self.slowmodeSeconds)), ("slowmodeNextSendDate", ConstructorParameterDescription(self.slowmodeNextSendDate)), ("statsDc", ConstructorParameterDescription(self.statsDc)), ("pts", ConstructorParameterDescription(self.pts)), ("call", ConstructorParameterDescription(self.call)), ("ttlPeriod", ConstructorParameterDescription(self.ttlPeriod)), ("pendingSuggestions", ConstructorParameterDescription(self.pendingSuggestions)), ("groupcallDefaultJoinAs", ConstructorParameterDescription(self.groupcallDefaultJoinAs)), ("themeEmoticon", ConstructorParameterDescription(self.themeEmoticon)), ("requestsPending", ConstructorParameterDescription(self.requestsPending)), ("recentRequesters", ConstructorParameterDescription(self.recentRequesters)), ("defaultSendAs", ConstructorParameterDescription(self.defaultSendAs)), ("availableReactions", ConstructorParameterDescription(self.availableReactions)), ("reactionsLimit", ConstructorParameterDescription(self.reactionsLimit)), ("stories", ConstructorParameterDescription(self.stories)), ("wallpaper", ConstructorParameterDescription(self.wallpaper)), ("boostsApplied", ConstructorParameterDescription(self.boostsApplied)), ("boostsUnrestrict", ConstructorParameterDescription(self.boostsUnrestrict)), ("emojiset", ConstructorParameterDescription(self.emojiset)), ("botVerification", ConstructorParameterDescription(self.botVerification)), ("stargiftsCount", ConstructorParameterDescription(self.stargiftsCount)), ("sendPaidMessagesStars", ConstructorParameterDescription(self.sendPaidMessagesStars)), ("mainTab", ConstructorParameterDescription(self.mainTab))])
return ("channelFull", [("flags", ConstructorParameterDescription(self.flags)), ("flags2", ConstructorParameterDescription(self.flags2)), ("id", ConstructorParameterDescription(self.id)), ("about", ConstructorParameterDescription(self.about)), ("participantsCount", ConstructorParameterDescription(self.participantsCount)), ("adminsCount", ConstructorParameterDescription(self.adminsCount)), ("kickedCount", ConstructorParameterDescription(self.kickedCount)), ("bannedCount", ConstructorParameterDescription(self.bannedCount)), ("onlineCount", ConstructorParameterDescription(self.onlineCount)), ("readInboxMaxId", ConstructorParameterDescription(self.readInboxMaxId)), ("readOutboxMaxId", ConstructorParameterDescription(self.readOutboxMaxId)), ("unreadCount", ConstructorParameterDescription(self.unreadCount)), ("chatPhoto", ConstructorParameterDescription(self.chatPhoto)), ("notifySettings", ConstructorParameterDescription(self.notifySettings)), ("exportedInvite", ConstructorParameterDescription(self.exportedInvite)), ("botInfo", ConstructorParameterDescription(self.botInfo)), ("migratedFromChatId", ConstructorParameterDescription(self.migratedFromChatId)), ("migratedFromMaxId", ConstructorParameterDescription(self.migratedFromMaxId)), ("pinnedMsgId", ConstructorParameterDescription(self.pinnedMsgId)), ("stickerset", ConstructorParameterDescription(self.stickerset)), ("availableMinId", ConstructorParameterDescription(self.availableMinId)), ("folderId", ConstructorParameterDescription(self.folderId)), ("linkedChatId", ConstructorParameterDescription(self.linkedChatId)), ("location", ConstructorParameterDescription(self.location)), ("slowmodeSeconds", ConstructorParameterDescription(self.slowmodeSeconds)), ("slowmodeNextSendDate", ConstructorParameterDescription(self.slowmodeNextSendDate)), ("statsDc", ConstructorParameterDescription(self.statsDc)), ("pts", ConstructorParameterDescription(self.pts)), ("call", ConstructorParameterDescription(self.call)), ("ttlPeriod", ConstructorParameterDescription(self.ttlPeriod)), ("pendingSuggestions", ConstructorParameterDescription(self.pendingSuggestions)), ("groupcallDefaultJoinAs", ConstructorParameterDescription(self.groupcallDefaultJoinAs)), ("themeEmoticon", ConstructorParameterDescription(self.themeEmoticon)), ("requestsPending", ConstructorParameterDescription(self.requestsPending)), ("recentRequesters", ConstructorParameterDescription(self.recentRequesters)), ("defaultSendAs", ConstructorParameterDescription(self.defaultSendAs)), ("availableReactions", ConstructorParameterDescription(self.availableReactions)), ("reactionsLimit", ConstructorParameterDescription(self.reactionsLimit)), ("stories", ConstructorParameterDescription(self.stories)), ("wallpaper", ConstructorParameterDescription(self.wallpaper)), ("boostsApplied", ConstructorParameterDescription(self.boostsApplied)), ("boostsUnrestrict", ConstructorParameterDescription(self.boostsUnrestrict)), ("emojiset", ConstructorParameterDescription(self.emojiset)), ("botVerification", ConstructorParameterDescription(self.botVerification)), ("stargiftsCount", ConstructorParameterDescription(self.stargiftsCount)), ("sendPaidMessagesStars", ConstructorParameterDescription(self.sendPaidMessagesStars)), ("mainTab", ConstructorParameterDescription(self.mainTab)), ("guardBotId", ConstructorParameterDescription(self.guardBotId))])
}
}
public class Cons_chatFull: TypeConstructorDescription {
@ -1553,7 +1555,7 @@ public extension Api {
switch self {
case .channelFull(let _data):
if boxed {
buffer.appendInt32(-455036259)
buffer.appendInt32(-1605464774)
}
serializeInt32(_data.flags, buffer: buffer, boxed: false)
serializeInt32(_data.flags2, buffer: buffer, boxed: false)
@ -1686,6 +1688,9 @@ public extension Api {
if Int(_data.flags2) & Int(1 << 22) != 0 {
_data.mainTab!.serialize(buffer, true)
}
if Int(_data.flags2) & Int(1 << 23) != 0 {
serializeInt64(_data.guardBotId!, buffer: buffer, boxed: false)
}
break
case .chatFull(let _data):
if boxed {
@ -1750,7 +1755,7 @@ public extension Api {
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
switch self {
case .channelFull(let _data):
return ("channelFull", [("flags", ConstructorParameterDescription(_data.flags)), ("flags2", ConstructorParameterDescription(_data.flags2)), ("id", ConstructorParameterDescription(_data.id)), ("about", ConstructorParameterDescription(_data.about)), ("participantsCount", ConstructorParameterDescription(_data.participantsCount)), ("adminsCount", ConstructorParameterDescription(_data.adminsCount)), ("kickedCount", ConstructorParameterDescription(_data.kickedCount)), ("bannedCount", ConstructorParameterDescription(_data.bannedCount)), ("onlineCount", ConstructorParameterDescription(_data.onlineCount)), ("readInboxMaxId", ConstructorParameterDescription(_data.readInboxMaxId)), ("readOutboxMaxId", ConstructorParameterDescription(_data.readOutboxMaxId)), ("unreadCount", ConstructorParameterDescription(_data.unreadCount)), ("chatPhoto", ConstructorParameterDescription(_data.chatPhoto)), ("notifySettings", ConstructorParameterDescription(_data.notifySettings)), ("exportedInvite", ConstructorParameterDescription(_data.exportedInvite)), ("botInfo", ConstructorParameterDescription(_data.botInfo)), ("migratedFromChatId", ConstructorParameterDescription(_data.migratedFromChatId)), ("migratedFromMaxId", ConstructorParameterDescription(_data.migratedFromMaxId)), ("pinnedMsgId", ConstructorParameterDescription(_data.pinnedMsgId)), ("stickerset", ConstructorParameterDescription(_data.stickerset)), ("availableMinId", ConstructorParameterDescription(_data.availableMinId)), ("folderId", ConstructorParameterDescription(_data.folderId)), ("linkedChatId", ConstructorParameterDescription(_data.linkedChatId)), ("location", ConstructorParameterDescription(_data.location)), ("slowmodeSeconds", ConstructorParameterDescription(_data.slowmodeSeconds)), ("slowmodeNextSendDate", ConstructorParameterDescription(_data.slowmodeNextSendDate)), ("statsDc", ConstructorParameterDescription(_data.statsDc)), ("pts", ConstructorParameterDescription(_data.pts)), ("call", ConstructorParameterDescription(_data.call)), ("ttlPeriod", ConstructorParameterDescription(_data.ttlPeriod)), ("pendingSuggestions", ConstructorParameterDescription(_data.pendingSuggestions)), ("groupcallDefaultJoinAs", ConstructorParameterDescription(_data.groupcallDefaultJoinAs)), ("themeEmoticon", ConstructorParameterDescription(_data.themeEmoticon)), ("requestsPending", ConstructorParameterDescription(_data.requestsPending)), ("recentRequesters", ConstructorParameterDescription(_data.recentRequesters)), ("defaultSendAs", ConstructorParameterDescription(_data.defaultSendAs)), ("availableReactions", ConstructorParameterDescription(_data.availableReactions)), ("reactionsLimit", ConstructorParameterDescription(_data.reactionsLimit)), ("stories", ConstructorParameterDescription(_data.stories)), ("wallpaper", ConstructorParameterDescription(_data.wallpaper)), ("boostsApplied", ConstructorParameterDescription(_data.boostsApplied)), ("boostsUnrestrict", ConstructorParameterDescription(_data.boostsUnrestrict)), ("emojiset", ConstructorParameterDescription(_data.emojiset)), ("botVerification", ConstructorParameterDescription(_data.botVerification)), ("stargiftsCount", ConstructorParameterDescription(_data.stargiftsCount)), ("sendPaidMessagesStars", ConstructorParameterDescription(_data.sendPaidMessagesStars)), ("mainTab", ConstructorParameterDescription(_data.mainTab))])
return ("channelFull", [("flags", ConstructorParameterDescription(_data.flags)), ("flags2", ConstructorParameterDescription(_data.flags2)), ("id", ConstructorParameterDescription(_data.id)), ("about", ConstructorParameterDescription(_data.about)), ("participantsCount", ConstructorParameterDescription(_data.participantsCount)), ("adminsCount", ConstructorParameterDescription(_data.adminsCount)), ("kickedCount", ConstructorParameterDescription(_data.kickedCount)), ("bannedCount", ConstructorParameterDescription(_data.bannedCount)), ("onlineCount", ConstructorParameterDescription(_data.onlineCount)), ("readInboxMaxId", ConstructorParameterDescription(_data.readInboxMaxId)), ("readOutboxMaxId", ConstructorParameterDescription(_data.readOutboxMaxId)), ("unreadCount", ConstructorParameterDescription(_data.unreadCount)), ("chatPhoto", ConstructorParameterDescription(_data.chatPhoto)), ("notifySettings", ConstructorParameterDescription(_data.notifySettings)), ("exportedInvite", ConstructorParameterDescription(_data.exportedInvite)), ("botInfo", ConstructorParameterDescription(_data.botInfo)), ("migratedFromChatId", ConstructorParameterDescription(_data.migratedFromChatId)), ("migratedFromMaxId", ConstructorParameterDescription(_data.migratedFromMaxId)), ("pinnedMsgId", ConstructorParameterDescription(_data.pinnedMsgId)), ("stickerset", ConstructorParameterDescription(_data.stickerset)), ("availableMinId", ConstructorParameterDescription(_data.availableMinId)), ("folderId", ConstructorParameterDescription(_data.folderId)), ("linkedChatId", ConstructorParameterDescription(_data.linkedChatId)), ("location", ConstructorParameterDescription(_data.location)), ("slowmodeSeconds", ConstructorParameterDescription(_data.slowmodeSeconds)), ("slowmodeNextSendDate", ConstructorParameterDescription(_data.slowmodeNextSendDate)), ("statsDc", ConstructorParameterDescription(_data.statsDc)), ("pts", ConstructorParameterDescription(_data.pts)), ("call", ConstructorParameterDescription(_data.call)), ("ttlPeriod", ConstructorParameterDescription(_data.ttlPeriod)), ("pendingSuggestions", ConstructorParameterDescription(_data.pendingSuggestions)), ("groupcallDefaultJoinAs", ConstructorParameterDescription(_data.groupcallDefaultJoinAs)), ("themeEmoticon", ConstructorParameterDescription(_data.themeEmoticon)), ("requestsPending", ConstructorParameterDescription(_data.requestsPending)), ("recentRequesters", ConstructorParameterDescription(_data.recentRequesters)), ("defaultSendAs", ConstructorParameterDescription(_data.defaultSendAs)), ("availableReactions", ConstructorParameterDescription(_data.availableReactions)), ("reactionsLimit", ConstructorParameterDescription(_data.reactionsLimit)), ("stories", ConstructorParameterDescription(_data.stories)), ("wallpaper", ConstructorParameterDescription(_data.wallpaper)), ("boostsApplied", ConstructorParameterDescription(_data.boostsApplied)), ("boostsUnrestrict", ConstructorParameterDescription(_data.boostsUnrestrict)), ("emojiset", ConstructorParameterDescription(_data.emojiset)), ("botVerification", ConstructorParameterDescription(_data.botVerification)), ("stargiftsCount", ConstructorParameterDescription(_data.stargiftsCount)), ("sendPaidMessagesStars", ConstructorParameterDescription(_data.sendPaidMessagesStars)), ("mainTab", ConstructorParameterDescription(_data.mainTab)), ("guardBotId", ConstructorParameterDescription(_data.guardBotId))])
case .chatFull(let _data):
return ("chatFull", [("flags", ConstructorParameterDescription(_data.flags)), ("id", ConstructorParameterDescription(_data.id)), ("about", ConstructorParameterDescription(_data.about)), ("participants", ConstructorParameterDescription(_data.participants)), ("chatPhoto", ConstructorParameterDescription(_data.chatPhoto)), ("notifySettings", ConstructorParameterDescription(_data.notifySettings)), ("exportedInvite", ConstructorParameterDescription(_data.exportedInvite)), ("botInfo", ConstructorParameterDescription(_data.botInfo)), ("pinnedMsgId", ConstructorParameterDescription(_data.pinnedMsgId)), ("folderId", ConstructorParameterDescription(_data.folderId)), ("call", ConstructorParameterDescription(_data.call)), ("ttlPeriod", ConstructorParameterDescription(_data.ttlPeriod)), ("groupcallDefaultJoinAs", ConstructorParameterDescription(_data.groupcallDefaultJoinAs)), ("themeEmoticon", ConstructorParameterDescription(_data.themeEmoticon)), ("requestsPending", ConstructorParameterDescription(_data.requestsPending)), ("recentRequesters", ConstructorParameterDescription(_data.recentRequesters)), ("availableReactions", ConstructorParameterDescription(_data.availableReactions)), ("reactionsLimit", ConstructorParameterDescription(_data.reactionsLimit))])
}
@ -1957,6 +1962,10 @@ public extension Api {
_47 = Api.parse(reader, signature: signature) as? Api.ProfileTab
}
}
var _48: Int64?
if Int(_2 ?? 0) & Int(1 << 23) != 0 {
_48 = reader.readInt64()
}
let _c1 = _1 != nil
let _c2 = _2 != nil
let _c3 = _3 != nil
@ -2004,8 +2013,9 @@ public extension Api {
let _c45 = (Int(_2 ?? 0) & Int(1 << 18) == 0) || _45 != nil
let _c46 = (Int(_2 ?? 0) & Int(1 << 21) == 0) || _46 != nil
let _c47 = (Int(_2 ?? 0) & Int(1 << 22) == 0) || _47 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 && _c43 && _c44 && _c45 && _c46 && _c47 {
return Api.ChatFull.channelFull(Cons_channelFull(flags: _1!, flags2: _2!, id: _3!, about: _4!, participantsCount: _5, adminsCount: _6, kickedCount: _7, bannedCount: _8, onlineCount: _9, readInboxMaxId: _10!, readOutboxMaxId: _11!, unreadCount: _12!, chatPhoto: _13!, notifySettings: _14!, exportedInvite: _15, botInfo: _16!, migratedFromChatId: _17, migratedFromMaxId: _18, pinnedMsgId: _19, stickerset: _20, availableMinId: _21, folderId: _22, linkedChatId: _23, location: _24, slowmodeSeconds: _25, slowmodeNextSendDate: _26, statsDc: _27, pts: _28!, call: _29, ttlPeriod: _30, pendingSuggestions: _31, groupcallDefaultJoinAs: _32, themeEmoticon: _33, requestsPending: _34, recentRequesters: _35, defaultSendAs: _36, availableReactions: _37, reactionsLimit: _38, stories: _39, wallpaper: _40, boostsApplied: _41, boostsUnrestrict: _42, emojiset: _43, botVerification: _44, stargiftsCount: _45, sendPaidMessagesStars: _46, mainTab: _47))
let _c48 = (Int(_2 ?? 0) & Int(1 << 23) == 0) || _48 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 && _c8 && _c9 && _c10 && _c11 && _c12 && _c13 && _c14 && _c15 && _c16 && _c17 && _c18 && _c19 && _c20 && _c21 && _c22 && _c23 && _c24 && _c25 && _c26 && _c27 && _c28 && _c29 && _c30 && _c31 && _c32 && _c33 && _c34 && _c35 && _c36 && _c37 && _c38 && _c39 && _c40 && _c41 && _c42 && _c43 && _c44 && _c45 && _c46 && _c47 && _c48 {
return Api.ChatFull.channelFull(Cons_channelFull(flags: _1!, flags2: _2!, id: _3!, about: _4!, participantsCount: _5, adminsCount: _6, kickedCount: _7, bannedCount: _8, onlineCount: _9, readInboxMaxId: _10!, readOutboxMaxId: _11!, unreadCount: _12!, chatPhoto: _13!, notifySettings: _14!, exportedInvite: _15, botInfo: _16!, migratedFromChatId: _17, migratedFromMaxId: _18, pinnedMsgId: _19, stickerset: _20, availableMinId: _21, folderId: _22, linkedChatId: _23, location: _24, slowmodeSeconds: _25, slowmodeNextSendDate: _26, statsDc: _27, pts: _28!, call: _29, ttlPeriod: _30, pendingSuggestions: _31, groupcallDefaultJoinAs: _32, themeEmoticon: _33, requestsPending: _34, recentRequesters: _35, defaultSendAs: _36, availableReactions: _37, reactionsLimit: _38, stories: _39, wallpaper: _40, boostsApplied: _41, boostsUnrestrict: _42, emojiset: _43, botVerification: _44, stargiftsCount: _45, sendPaidMessagesStars: _46, mainTab: _47, guardBotId: _48))
}
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

View file

@ -1094,14 +1094,20 @@ public extension Api {
public var botId: Int64
public var recipients: Api.BusinessBotRecipients
public var rights: Api.BusinessBotRights
public init(flags: Int32, botId: Int64, recipients: Api.BusinessBotRecipients, rights: Api.BusinessBotRights) {
public var device: String?
public var date: Int32?
public var location: String?
public init(flags: Int32, botId: Int64, recipients: Api.BusinessBotRecipients, rights: Api.BusinessBotRights, device: String?, date: Int32?, location: String?) {
self.flags = flags
self.botId = botId
self.recipients = recipients
self.rights = rights
self.device = device
self.date = date
self.location = location
}
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
return ("connectedBot", [("flags", ConstructorParameterDescription(self.flags)), ("botId", ConstructorParameterDescription(self.botId)), ("recipients", ConstructorParameterDescription(self.recipients)), ("rights", ConstructorParameterDescription(self.rights))])
return ("connectedBot", [("flags", ConstructorParameterDescription(self.flags)), ("botId", ConstructorParameterDescription(self.botId)), ("recipients", ConstructorParameterDescription(self.recipients)), ("rights", ConstructorParameterDescription(self.rights)), ("device", ConstructorParameterDescription(self.device)), ("date", ConstructorParameterDescription(self.date)), ("location", ConstructorParameterDescription(self.location))])
}
}
case connectedBot(Cons_connectedBot)
@ -1110,12 +1116,21 @@ public extension Api {
switch self {
case .connectedBot(let _data):
if boxed {
buffer.appendInt32(-849058964)
buffer.appendInt32(54448129)
}
serializeInt32(_data.flags, buffer: buffer, boxed: false)
serializeInt64(_data.botId, buffer: buffer, boxed: false)
_data.recipients.serialize(buffer, true)
_data.rights.serialize(buffer, true)
if Int(_data.flags) & Int(1 << 0) != 0 {
serializeString(_data.device!, buffer: buffer, boxed: false)
}
if Int(_data.flags) & Int(1 << 1) != 0 {
serializeInt32(_data.date!, buffer: buffer, boxed: false)
}
if Int(_data.flags) & Int(1 << 2) != 0 {
serializeString(_data.location!, buffer: buffer, boxed: false)
}
break
}
}
@ -1123,7 +1138,7 @@ public extension Api {
public func descriptionFields() -> (String, [(String, ConstructorParameterDescription)]) {
switch self {
case .connectedBot(let _data):
return ("connectedBot", [("flags", ConstructorParameterDescription(_data.flags)), ("botId", ConstructorParameterDescription(_data.botId)), ("recipients", ConstructorParameterDescription(_data.recipients)), ("rights", ConstructorParameterDescription(_data.rights))])
return ("connectedBot", [("flags", ConstructorParameterDescription(_data.flags)), ("botId", ConstructorParameterDescription(_data.botId)), ("recipients", ConstructorParameterDescription(_data.recipients)), ("rights", ConstructorParameterDescription(_data.rights)), ("device", ConstructorParameterDescription(_data.device)), ("date", ConstructorParameterDescription(_data.date)), ("location", ConstructorParameterDescription(_data.location))])
}
}
@ -1140,12 +1155,27 @@ public extension Api {
if let signature = reader.readInt32() {
_4 = Api.parse(reader, signature: signature) as? Api.BusinessBotRights
}
var _5: String?
if Int(_1 ?? 0) & Int(1 << 0) != 0 {
_5 = parseString(reader)
}
var _6: Int32?
if Int(_1 ?? 0) & Int(1 << 1) != 0 {
_6 = reader.readInt32()
}
var _7: String?
if Int(_1 ?? 0) & Int(1 << 2) != 0 {
_7 = 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.ConnectedBot.connectedBot(Cons_connectedBot(flags: _1!, botId: _2!, recipients: _3!, rights: _4!))
let _c5 = (Int(_1 ?? 0) & Int(1 << 0) == 0) || _5 != nil
let _c6 = (Int(_1 ?? 0) & Int(1 << 1) == 0) || _6 != nil
let _c7 = (Int(_1 ?? 0) & Int(1 << 2) == 0) || _7 != nil
if _c1 && _c2 && _c3 && _c4 && _c5 && _c6 && _c7 {
return Api.ConnectedBot.connectedBot(Cons_connectedBot(flags: _1!, botId: _2!, recipients: _3!, rights: _4!, device: _5, date: _6, location: _7))
}
else {
return nil

View file

@ -103,6 +103,7 @@ private var declaredEncodables: Void = {
declareEncodable(InlineBotMessageAttribute.self, f: { InlineBotMessageAttribute(decoder: $0) })
declareEncodable(InlineBusinessBotMessageAttribute.self, f: { InlineBusinessBotMessageAttribute(decoder: $0) })
declareEncodable(TextEntitiesMessageAttribute.self, f: { TextEntitiesMessageAttribute(decoder: $0) })
declareEncodable(RichTextMessageAttribute.self, f: { RichTextMessageAttribute(decoder: $0) })
declareEncodable(ReplyMessageAttribute.self, f: { ReplyMessageAttribute(decoder: $0) })
declareEncodable(QuotedReplyMessageAttribute.self, f: { QuotedReplyMessageAttribute(decoder: $0) })
declareEncodable(ReplyStoryAttribute.self, f: { ReplyStoryAttribute(decoder: $0) })

View file

@ -48,38 +48,128 @@ extension InstantPageListItem {
self = .blocks(blocks.map({ InstantPageBlock(apiBlock: $0) }), num)
}
}
func apiInputPageListItem() -> Api.PageListItem {
switch self {
case let .text(value, _):
return .pageListItemText(Api.PageListItem.Cons_pageListItemText(flags: 0, text: value.apiRichText()))
case let .blocks(blocks, _):
return .pageListItemBlocks(Api.PageListItem.Cons_pageListItemBlocks(flags: 0, blocks: blocks.compactMap { $0.apiInputBlock() }))
case .unknown:
return .pageListItemText(Api.PageListItem.Cons_pageListItemText(flags: 0, text: .textPlain(Api.RichText.Cons_textPlain(text: ""))))
}
}
func apiInputPageOrderedListItem() -> Api.InputPageListOrderedItem {
switch self {
case let .text(value, num):
var flags: Int32 = 0
var inputNum: Int32?
if let num, let numValue = Int32(num) {
inputNum = numValue
flags |= (1 << 2)
}
return .inputPageListOrderedItemText(Api.InputPageListOrderedItem.Cons_inputPageListOrderedItemText(flags: flags, text: value.apiRichText(), value: inputNum, type: nil))
case let .blocks(blocks, num):
var flags: Int32 = 0
var inputNum: Int32?
if let num, let numValue = Int32(num) {
inputNum = numValue
flags |= (1 << 2)
}
return .inputPageListOrderedItemBlocks(Api.InputPageListOrderedItem.Cons_inputPageListOrderedItemBlocks(flags: flags, blocks: blocks.compactMap { $0.apiInputBlock() }, value: inputNum, type: nil))
case .unknown:
return .inputPageListOrderedItemText(Api.InputPageListOrderedItem.Cons_inputPageListOrderedItemText(flags: 0, text: .textPlain(Api.RichText.Cons_textPlain(text: "")), value: nil, type: nil))
}
}
}
extension InstantPageTableCell {
convenience init(apiTableCell: Api.PageTableCell) {
switch apiTableCell {
case let .pageTableCell(pageTableCellData):
let (flags, text, colspan, rowspan) = (pageTableCellData.flags, pageTableCellData.text, pageTableCellData.colspan, pageTableCellData.rowspan)
var alignment = TableHorizontalAlignment.left
if (flags & (1 << 3)) != 0 {
alignment = .center
} else if (flags & (1 << 4)) != 0 {
alignment = .right
}
var verticalAlignment = TableVerticalAlignment.top
if (flags & (1 << 5)) != 0 {
verticalAlignment = .middle
} else if (flags & (1 << 6)) != 0 {
verticalAlignment = .bottom
}
self.init(text: text != nil ? RichText(apiText: text!) : nil, header: (flags & (1 << 0)) != 0, alignment: alignment, verticalAlignment: verticalAlignment, colspan: colspan ?? 0, rowspan: rowspan ?? 0)
case let .pageTableCell(pageTableCellData):
let (flags, text, colspan, rowspan) = (pageTableCellData.flags, pageTableCellData.text, pageTableCellData.colspan, pageTableCellData.rowspan)
var alignment = TableHorizontalAlignment.left
if (flags & (1 << 3)) != 0 {
alignment = .center
} else if (flags & (1 << 4)) != 0 {
alignment = .right
}
var verticalAlignment = TableVerticalAlignment.top
if (flags & (1 << 5)) != 0 {
verticalAlignment = .middle
} else if (flags & (1 << 6)) != 0 {
verticalAlignment = .bottom
}
self.init(text: text != nil ? RichText(apiText: text!) : nil, header: (flags & (1 << 0)) != 0, alignment: alignment, verticalAlignment: verticalAlignment, colspan: colspan ?? 0, rowspan: rowspan ?? 0)
}
}
func inputPageTableCell() -> Api.PageTableCell {
var flags: Int32 = 0
switch self.alignment {
case .left:
break
case .center:
flags |= (1 << 3)
case .right:
flags |= (1 << 4)
}
switch self.verticalAlignment {
case .top:
break
case .middle:
flags |= (1 << 5)
case .bottom:
flags |= (1 << 6)
}
if self.header {
flags |= (1 << 0)
}
var inputText: Api.RichText?
if let text = self.text {
inputText = text.apiRichText()
if inputText != nil {
flags |= (1 << 7)
}
}
var inputColspan: Int32?
if self.colspan != 0 {
inputColspan = self.colspan
flags |= (1 << 1)
}
var inputRowspan: Int32?
if self.rowspan != 0 {
inputRowspan = self.rowspan
flags |= (1 << 2)
}
return .pageTableCell(Api.PageTableCell.Cons_pageTableCell(flags: flags, text: inputText, colspan: inputColspan, rowspan: inputRowspan))
}
}
extension InstantPageTableRow {
convenience init(apiTableRow: Api.PageTableRow) {
switch apiTableRow {
case let .pageTableRow(pageTableRowData):
let cells = pageTableRowData.cells
self.init(cells: cells.map({ InstantPageTableCell(apiTableCell: $0) }))
case let .pageTableRow(pageTableRowData):
let cells = pageTableRowData.cells
self.init(cells: cells.map({ InstantPageTableCell(apiTableCell: $0) }))
}
}
func inputPageTableRow() -> Api.PageTableRow {
return .pageTableRow(Api.PageTableRow.Cons_pageTableRow(cells: self.cells.map { $0.inputPageTableCell() }))
}
}
extension InstantPageRelatedArticle {
@ -198,6 +288,104 @@ extension InstantPageBlock {
default:
self = .unsupported
}
case let .pageBlockHeading1(pageBlockHeading1):
self = .heading(text: RichText(apiText: pageBlockHeading1.text), level: 1)
case let .pageBlockHeading2(pageBlockHeading2):
self = .heading(text: RichText(apiText: pageBlockHeading2.text), level: 2)
case let .pageBlockHeading3(pageBlockHeading3):
self = .heading(text: RichText(apiText: pageBlockHeading3.text), level: 3)
case let .pageBlockHeading4(pageBlockHeading4):
self = .heading(text: RichText(apiText: pageBlockHeading4.text), level: 4)
case let .pageBlockHeading5(pageBlockHeading5):
self = .heading(text: RichText(apiText: pageBlockHeading5.text), level: 5)
case let .pageBlockHeading6(pageBlockHeading6):
self = .heading(text: RichText(apiText: pageBlockHeading6.text), level: 6)
case let .pageBlockMath(pageBlockMath):
self = .formula(latex: pageBlockMath.source)
case .inputPageBlockPhoto, .inputPageBlockVideo, .inputPageBlockAudio, .inputPageBlockMap, .inputPageBlockOrderedList:
self = .unsupported
}
}
func apiInputBlock() -> Api.PageBlock? {
switch self {
case .unsupported, .title, .subtitle, .kicker, .header, .subheader, .cover, .channelBanner, .authorDate, .relatedArticles, .webEmbed, .postEmbed:
return nil
case let .heading(text, level):
let block: Api.PageBlock
switch level {
case 0, 1:
block = .pageBlockHeading1(Api.PageBlock.Cons_pageBlockHeading1(text: text.apiRichText()))
case 2:
block = .pageBlockHeading2(Api.PageBlock.Cons_pageBlockHeading2(text: text.apiRichText()))
case 3:
block = .pageBlockHeading3(Api.PageBlock.Cons_pageBlockHeading3(text: text.apiRichText()))
case 4:
block = .pageBlockHeading4(Api.PageBlock.Cons_pageBlockHeading4(text: text.apiRichText()))
case 5:
block = .pageBlockHeading5(Api.PageBlock.Cons_pageBlockHeading5(text: text.apiRichText()))
default:
block = .pageBlockHeading6(Api.PageBlock.Cons_pageBlockHeading6(text: text.apiRichText()))
}
return block
case let .formula(latex):
return .pageBlockMath(Api.PageBlock.Cons_pageBlockMath(source: latex))
case let .paragraph(value):
return .pageBlockParagraph(Api.PageBlock.Cons_pageBlockParagraph(text: value.apiRichText()))
case let .preformatted(text, language):
return .pageBlockPreformatted(Api.PageBlock.Cons_pageBlockPreformatted(text: text.apiRichText(), language: language ?? ""))
case let .footer(value):
return .pageBlockFooter(Api.PageBlock.Cons_pageBlockFooter(text: value.apiRichText()))
case .divider:
return .pageBlockDivider
case let .anchor(value):
return .pageBlockAnchor(Api.PageBlock.Cons_pageBlockAnchor(name: value))
case let .list(items, ordered):
if ordered {
return .inputPageBlockOrderedList(Api.PageBlock.Cons_inputPageBlockOrderedList(flags: 0, items: items.map { $0.apiInputPageOrderedListItem() }, start: nil, type: nil))
} else {
return .pageBlockList(Api.PageBlock.Cons_pageBlockList(items: items.map { $0.apiInputPageListItem() }))
}
case let .blockQuote(text, caption):
return .pageBlockBlockquote(Api.PageBlock.Cons_pageBlockBlockquote(text: text.apiRichText(), caption: caption.apiRichText()))
case let .pullQuote(text, caption):
return .pageBlockPullquote(Api.PageBlock.Cons_pageBlockPullquote(text: text.apiRichText(), caption: caption.apiRichText()))
case let .image(id, caption, url, _):
//TODO:localize
let _ = id
assertionFailure()
return .inputPageBlockPhoto(Api.PageBlock.Cons_inputPageBlockPhoto(flags: 0, photo: .inputPhotoEmpty, caption: .pageCaption(Api.PageCaption.Cons_pageCaption(text: caption.text.apiRichText(), credit: caption.credit.apiRichText())), url: url))
case let .video(id, caption, autoplay, loop):
//TODO:localize
let _ = autoplay
let _ = loop
let _ = id
assertionFailure()
return .inputPageBlockVideo(Api.PageBlock.Cons_inputPageBlockVideo(flags: 0, video: .inputDocumentEmpty, caption: .pageCaption(Api.PageCaption.Cons_pageCaption(text: caption.text.apiRichText(), credit: caption.credit.apiRichText()))))
case let .audio(id, caption):
let _ = id
return .inputPageBlockAudio(Api.PageBlock.Cons_inputPageBlockAudio(audio: .inputDocumentEmpty, caption: .pageCaption(Api.PageCaption.Cons_pageCaption(text: caption.text.apiRichText(), credit: caption.credit.apiRichText()))))
case let .collage(items, caption):
return .pageBlockCollage(Api.PageBlock.Cons_pageBlockCollage(items: items.compactMap { $0.apiInputBlock() }, caption: .pageCaption(Api.PageCaption.Cons_pageCaption(text: caption.text.apiRichText(), credit: caption.credit.apiRichText()))))
case let .slideshow(items, caption):
return .pageBlockSlideshow(Api.PageBlock.Cons_pageBlockSlideshow(items: items.compactMap { $0.apiInputBlock() }, caption: .pageCaption(Api.PageCaption.Cons_pageCaption(text: caption.text.apiRichText(), credit: caption.credit.apiRichText()))))
case let .table(title, rows, bordered, striped):
var flags: Int32 = 0
if bordered {
flags |= (1 << 0)
}
if striped {
flags |= (1 << 1)
}
return .pageBlockTable(Api.PageBlock.Cons_pageBlockTable(flags: flags, title: title.apiRichText(), rows: rows.map { $0.inputPageTableRow() }))
case let .details(title, blocks, expanded):
var flags: Int32 = 0
if expanded {
flags |= (1 << 0)
}
return .pageBlockDetails(Api.PageBlock.Cons_pageBlockDetails(flags: flags, blocks: blocks.compactMap { $0.apiInputBlock() }, title: title.apiRichText()))
case let .map(latitude, longitude, zoom, dimensions, caption):
return .inputPageBlockMap(Api.PageBlock.Cons_inputPageBlockMap(geo: .inputGeoPoint(Api.InputGeoPoint.Cons_inputGeoPoint(flags: 0, lat: latitude, long: longitude, accuracyRadius: nil)), zoom: zoom, w: dimensions.width, h: dimensions.height, caption: .pageCaption(Api.PageCaption.Cons_pageCaption(text: caption.text.apiRichText(), credit: caption.credit.apiRichText()))))
}
}
}
@ -212,15 +400,15 @@ extension InstantPage {
let url: String
let views: Int32?
switch apiPage {
case let .page(pageData):
let (flags, pageUrl, pageBlocks, pagePhotos, pageDocuments, pageViews) = (pageData.flags, pageData.url, pageData.blocks, pageData.photos, pageData.documents, pageData.views)
url = pageUrl
blocks = pageBlocks
photos = pagePhotos
files = pageDocuments
isComplete = (flags & (1 << 0)) == 0
rtl = (flags & (1 << 1)) != 0
views = pageViews
case let .page(pageData):
let (flags, pageUrl, pageBlocks, pagePhotos, pageDocuments, pageViews) = (pageData.flags, pageData.url, pageData.blocks, pageData.photos, pageData.documents, pageData.views)
url = pageUrl
blocks = pageBlocks
photos = pagePhotos
files = pageDocuments
isComplete = (flags & (1 << 0)) == 0
rtl = (flags & (1 << 1)) != 0
views = pageViews
}
var media: [MediaId: Media] = [:]
for photo in photos {

View file

@ -6,53 +6,102 @@ import TelegramApi
extension RichText {
init(apiText: Api.RichText) {
switch apiText {
case .textEmpty:
self = .empty
case let .textPlain(textPlainData):
let text = textPlainData.text
self = .plain(text)
case let .textBold(textBoldData):
let text = textBoldData.text
self = .bold(RichText(apiText: text))
case let .textItalic(textItalicData):
let text = textItalicData.text
self = .italic(RichText(apiText: text))
case let .textUnderline(textUnderlineData):
let text = textUnderlineData.text
self = .underline(RichText(apiText: text))
case let .textStrike(textStrikeData):
let text = textStrikeData.text
self = .strikethrough(RichText(apiText: text))
case let .textFixed(textFixedData):
let text = textFixedData.text
self = .fixed(RichText(apiText: text))
case let .textUrl(textUrlData):
let (text, url, webpageId) = (textUrlData.text, textUrlData.url, textUrlData.webpageId)
self = .url(text: RichText(apiText: text), url: url, webpageId: webpageId == 0 ? nil : MediaId(namespace: Namespaces.Media.CloudWebpage, id: webpageId))
case let .textEmail(textEmailData):
let (text, email) = (textEmailData.text, textEmailData.email)
self = .email(text: RichText(apiText: text), email: email)
case let .textConcat(textConcatData):
let texts = textConcatData.texts
self = .concat(texts.map({ RichText(apiText: $0) }))
case let .textSubscript(textSubscriptData):
let text = textSubscriptData.text
self = .subscript(RichText(apiText: text))
case let .textSuperscript(textSuperscriptData):
let text = textSuperscriptData.text
self = .superscript(RichText(apiText: text))
case let .textMarked(textMarkedData):
let text = textMarkedData.text
self = .marked(RichText(apiText: text))
case let .textPhone(textPhoneData):
let (text, phone) = (textPhoneData.text, textPhoneData.phone)
self = .phone(text: RichText(apiText: text), phone: phone)
case let .textImage(textImageData):
let (documentId, w, h) = (textImageData.documentId, textImageData.w, textImageData.h)
self = .image(id: MediaId(namespace: Namespaces.Media.CloudFile, id: documentId), dimensions: PixelDimensions(width: w, height: h))
case let .textAnchor(textAnchorData):
let (text, name) = (textAnchorData.text, textAnchorData.name)
self = .anchor(text: RichText(apiText: text), name: name)
case .textEmpty:
self = .empty
case let .textPlain(textPlainData):
let text = textPlainData.text
self = .plain(text)
case let .textBold(textBoldData):
let text = textBoldData.text
self = .bold(RichText(apiText: text))
case let .textItalic(textItalicData):
let text = textItalicData.text
self = .italic(RichText(apiText: text))
case let .textUnderline(textUnderlineData):
let text = textUnderlineData.text
self = .underline(RichText(apiText: text))
case let .textStrike(textStrikeData):
let text = textStrikeData.text
self = .strikethrough(RichText(apiText: text))
case let .textFixed(textFixedData):
let text = textFixedData.text
self = .fixed(RichText(apiText: text))
case let .textUrl(textUrlData):
let (text, url, webpageId) = (textUrlData.text, textUrlData.url, textUrlData.webpageId)
self = .url(text: RichText(apiText: text), url: url, webpageId: webpageId == 0 ? nil : MediaId(namespace: Namespaces.Media.CloudWebpage, id: webpageId))
case let .textEmail(textEmailData):
let (text, email) = (textEmailData.text, textEmailData.email)
self = .email(text: RichText(apiText: text), email: email)
case let .textConcat(textConcatData):
let texts = textConcatData.texts
self = .concat(texts.map({ RichText(apiText: $0) }))
case let .textSubscript(textSubscriptData):
let text = textSubscriptData.text
self = .subscript(RichText(apiText: text))
case let .textSuperscript(textSuperscriptData):
let text = textSuperscriptData.text
self = .superscript(RichText(apiText: text))
case let .textMarked(textMarkedData):
let text = textMarkedData.text
self = .marked(RichText(apiText: text))
case let .textPhone(textPhoneData):
let (text, phone) = (textPhoneData.text, textPhoneData.phone)
self = .phone(text: RichText(apiText: text), phone: phone)
case let .textImage(textImageData):
let (documentId, w, h) = (textImageData.documentId, textImageData.w, textImageData.h)
self = .image(id: MediaId(namespace: Namespaces.Media.CloudFile, id: documentId), dimensions: PixelDimensions(width: w, height: h))
case let .textAnchor(textAnchorData):
let (text, name) = (textAnchorData.text, textAnchorData.name)
self = .anchor(text: RichText(apiText: text), name: name)
case .inputTextImage:
self = .plain("")
case .textCustomEmoji:
//TODO:localize
self = .plain("")
case let .textMath(textMath):
self = .formula(latex: textMath.source)
}
}
func apiRichText() -> Api.RichText {
switch self {
case .empty:
return .textPlain(Api.RichText.Cons_textPlain(text: ""))
case let .plain(value):
return .textPlain(Api.RichText.Cons_textPlain(text: value))
case let .bold(value):
return .textBold(Api.RichText.Cons_textBold(text: value.apiRichText()))
case let .italic(value):
return .textItalic(Api.RichText.Cons_textItalic(text: value.apiRichText()))
case let .underline(value):
return .textUnderline(Api.RichText.Cons_textUnderline(text: value.apiRichText()))
case let .strikethrough(value):
return .textStrike(Api.RichText.Cons_textStrike(text: value.apiRichText()))
case let .fixed(value):
return .textFixed(Api.RichText.Cons_textFixed(text: value.apiRichText()))
case let .url(text, url, webpageId):
return .textUrl(Api.RichText.Cons_textUrl(text: text.apiRichText(), url: url, webpageId: webpageId?.id ?? 0))
case let .email(text, email):
return .textEmail(Api.RichText.Cons_textEmail(text: text.apiRichText(), email: email))
case let .concat(values):
return .textConcat(Api.RichText.Cons_textConcat(texts: values.map { $0.apiRichText() }))
case let .`subscript`(value):
return .textSubscript(Api.RichText.Cons_textSubscript(text: value.apiRichText()))
case let .superscript(value):
return .textSuperscript(Api.RichText.Cons_textSuperscript(text: value.apiRichText()))
case let .marked(value):
return .textMarked(Api.RichText.Cons_textMarked(text: value.apiRichText()))
case let .phone(text, phone):
return .textPhone(Api.RichText.Cons_textPhone(text: text.apiRichText(), phone: phone))
case let .image(id, dimensions):
//TODO:localize
let _ = id
assertionFailure()
return .inputTextImage(Api.RichText.Cons_inputTextImage(document: .inputDocumentEmpty, w: dimensions.width, h: dimensions.height))
case let .anchor(text, name):
return .textAnchor(Api.RichText.Cons_textAnchor(text: text.apiRichText(), name: name))
case let .formula(latex):
return .textMath(Api.RichText.Cons_textMath(source: latex))
}
}
}

View file

@ -848,7 +848,7 @@ extension StoreMessage {
convenience init?(apiMessage: Api.Message, accountPeerId: PeerId, peerIsForum: Bool, namespace: MessageId.Namespace = Namespaces.Message.Cloud) {
switch apiMessage {
case let .message(messageData):
let (flags, flags2, id, fromId, boosts, rank, chatPeerId, savedPeerId, fwdFrom, viaBotId, viaBusinessBotId, guestChatViaFrom, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId, messageEffectId, factCheck, reportDeliveryUntilDate, paidMessageStars, suggestedPost, scheduledRepeatPeriod, summaryFromLanguage) = (messageData.flags, messageData.flags2, messageData.id, messageData.fromId, messageData.fromBoostsApplied, messageData.fromRank, messageData.peerId, messageData.savedPeerId, messageData.fwdFrom, messageData.viaBotId, messageData.viaBusinessBotId, messageData.guestchatViaFrom, messageData.replyTo, messageData.date, messageData.message, messageData.media, messageData.replyMarkup, messageData.entities, messageData.views, messageData.forwards, messageData.replies, messageData.editDate, messageData.postAuthor, messageData.groupedId, messageData.reactions, messageData.restrictionReason, messageData.ttlPeriod, messageData.quickReplyShortcutId, messageData.effect, messageData.factcheck, messageData.reportDeliveryUntilDate, messageData.paidMessageStars, messageData.suggestedPost, messageData.scheduleRepeatPeriod, messageData.summaryFromLanguage)
let (flags, flags2, id, fromId, boosts, rank, chatPeerId, savedPeerId, fwdFrom, viaBotId, viaBusinessBotId, guestChatViaFrom, replyTo, date, message, media, replyMarkup, entities, views, forwards, replies, editDate, postAuthor, groupingId, reactions, restrictionReason, ttlPeriod, quickReplyShortcutId, messageEffectId, factCheck, reportDeliveryUntilDate, paidMessageStars, suggestedPost, scheduledRepeatPeriod, summaryFromLanguage) = (messageData.flags, messageData.flags2, messageData.id, messageData.fromId, messageData.fromBoostsApplied, messageData.fromRank, messageData.peerId, messageData.savedPeerId, messageData.fwdFrom, messageData.viaBotId, messageData.viaBusinessBotId, messageData.guestchatViaFrom, messageData.replyTo, messageData.date, messageData.message, messageData.media, messageData.replyMarkup, messageData.entities, messageData.views, messageData.forwards, messageData.replies, messageData.editDate, messageData.postAuthor, messageData.groupedId, messageData.reactions, messageData.restrictionReason, messageData.ttlPeriod, messageData.quickReplyShortcutId, messageData.effect, messageData.factcheck, messageData.reportDeliveryUntilDate, messageData.paidMessageStars, messageData.suggestedPost, messageData.scheduleRepeatPeriod, messageData.summaryFromLanguage)
var attributes: [MessageAttribute] = []
if (flags2 & (1 << 4)) != 0 {
@ -1133,7 +1133,7 @@ extension StoreMessage {
}
var entitiesAttribute: TextEntitiesMessageAttribute?
if let entities = entities, !entities.isEmpty {
if let entities, !entities.isEmpty {
let attribute = TextEntitiesMessageAttribute(entities: messageTextEntitiesFromApiEntities(entities))
entitiesAttribute = attribute
attributes.append(attribute)
@ -1155,6 +1155,10 @@ extension StoreMessage {
attributes.append(attribute)
}
}
if let richMessage = messageData.richMessage {
attributes.append(RichTextMessageAttribute(apiRichMessage: richMessage))
}
if (flags & (1 << 19)) != 0 {
attributes.append(ContentRequiresValidationMessageAttribute())

View file

@ -255,6 +255,8 @@ private func filterMessageAttributesForOutgoingMessage(_ attributes: [MessageAtt
switch attribute {
case _ as TextEntitiesMessageAttribute:
return true
case _ as RichTextMessageAttribute:
return true
case _ as InlineBotMessageAttribute:
return true
case _ as OutgoingMessageInfoAttribute:
@ -306,6 +308,8 @@ private func filterMessageAttributesForForwardedMessage(_ attributes: [MessageAt
switch attribute {
case _ as TextEntitiesMessageAttribute:
return true
case _ as RichTextMessageAttribute:
return true
case _ as InlineBotMessageAttribute:
return true
case _ as NotificationInfoMessageAttribute:

View file

@ -64,7 +64,7 @@ private final class PendingUpdateMessageManagerImpl {
}
}
func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?, disableUrlPreview: Bool) {
func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, richText: RichTextMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?, disableUrlPreview: Bool) {
if let context = self.contexts[messageId] {
self.contexts.removeValue(forKey: messageId)
context.disposable.dispose()
@ -75,7 +75,7 @@ private final class PendingUpdateMessageManagerImpl {
self.contexts[messageId] = context
let queue = self.queue
disposable.set((requestEditMessage(accountPeerId: self.stateManager.accountPeerId, postbox: self.postbox, network: self.network, stateManager: self.stateManager, transformOutgoingMessageMedia: self.transformOutgoingMessageMedia, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: nil, invertMediaAttribute: invertMediaAttribute)
disposable.set((requestEditMessage(accountPeerId: self.stateManager.accountPeerId, postbox: self.postbox, network: self.network, stateManager: self.stateManager, transformOutgoingMessageMedia: self.transformOutgoingMessageMedia, messageMediaPreuploadManager: self.messageMediaPreuploadManager, mediaReferenceRevalidationContext: self.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, richText: richText, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: nil, invertMediaAttribute: invertMediaAttribute)
|> deliverOn(self.queue)).start(next: { [weak self, weak context] value in
queue.async {
guard let strongSelf = self, let initialContext = context else {
@ -163,9 +163,9 @@ public final class PendingUpdateMessageManager {
})
}
public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute? = nil, invertMediaAttribute: InvertMediaMessageAttribute? = nil, disableUrlPreview: Bool = false) {
public func add(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, richText: RichTextMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute? = nil, invertMediaAttribute: InvertMediaMessageAttribute? = nil, disableUrlPreview: Bool = false) {
self.impl.with { impl in
impl.add(messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertMediaAttribute, disableUrlPreview: disableUrlPreview)
impl.add(messageId: messageId, text: text, media: media, entities: entities, richText: richText, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertMediaAttribute, disableUrlPreview: disableUrlPreview)
}
}

View file

@ -27,15 +27,15 @@ public enum RequestEditMessageError {
case invalidGrouping
}
func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, disableUrlPreview: Bool, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
return requestEditMessage(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, invertMediaAttribute: invertMediaAttribute)
func _internal_requestEditMessage(account: Account, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, richText: RichTextMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, disableUrlPreview: Bool, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
return requestEditMessage(accountPeerId: account.peerId, postbox: account.postbox, network: account.network, stateManager: account.stateManager, transformOutgoingMessageMedia: account.transformOutgoingMessageMedia, messageMediaPreuploadManager: account.messageMediaPreuploadManager, mediaReferenceRevalidationContext: account.mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, richText: richText, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, invertMediaAttribute: invertMediaAttribute)
}
func requestEditMessage(accountPeerId: PeerId, postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, disableUrlPreview: Bool, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
return requestEditMessageInternal(accountPeerId: accountPeerId, postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertMediaAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, forceReupload: false)
func requestEditMessage(accountPeerId: PeerId, postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, richText: RichTextMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, disableUrlPreview: Bool, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
return requestEditMessageInternal(accountPeerId: accountPeerId, postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, richText: richText, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertMediaAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, forceReupload: false)
|> `catch` { error -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> in
if case .invalidReference = error {
return requestEditMessageInternal(accountPeerId: accountPeerId, postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertMediaAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, forceReupload: true)
return requestEditMessageInternal(accountPeerId: accountPeerId, postbox: postbox, network: network, stateManager: stateManager, transformOutgoingMessageMedia: transformOutgoingMessageMedia, messageMediaPreuploadManager: messageMediaPreuploadManager, mediaReferenceRevalidationContext: mediaReferenceRevalidationContext, messageId: messageId, text: text, media: media, entities: entities, richText: richText, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertMediaAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, forceReupload: true)
} else {
return .fail(error)
}
@ -50,7 +50,7 @@ func requestEditMessage(accountPeerId: PeerId, postbox: Postbox, network: Networ
}
}
private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?, disableUrlPreview: Bool, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute?, forceReupload: Bool) -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> {
private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox, network: Network, stateManager: AccountStateManager, transformOutgoingMessageMedia: TransformOutgoingMessageMedia?, messageMediaPreuploadManager: MessageMediaPreuploadManager, mediaReferenceRevalidationContext: MediaReferenceRevalidationContext, messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, richText: RichTextMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute?, invertMediaAttribute: InvertMediaMessageAttribute?, disableUrlPreview: Bool, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute?, forceReupload: Bool) -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> {
let uploadedMedia: Signal<PendingMessageUploadedContentResult?, NoError>
switch media {
case .keep:
@ -146,15 +146,21 @@ private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox,
}
|> mapError { _ -> RequestEditMessageInternalError in }
|> mapToSignal { peer, message, associatedPeers -> Signal<RequestEditMessageResult, RequestEditMessageInternalError> in
if let peer = peer, let message = message, let inputPeer = apiInputPeer(peer) {
if let peer, let message, let inputPeer = apiInputPeer(peer) {
var flags: Int32 = 1 << 11
var apiEntities: [Api.MessageEntity]?
if let entities = entities {
if let entities {
apiEntities = apiTextAttributeEntities(entities, associatedPeers: associatedPeers)
flags |= Int32(1 << 3)
}
var apiRichMessage: Api.InputRichMessage?
if let richText {
apiRichMessage = richText.apiInputRichMessage()
flags |= Int32(1 << 23)
}
if disableUrlPreview {
flags |= Int32(1 << 1)
}
@ -201,7 +207,7 @@ private func requestEditMessageInternal(accountPeerId: PeerId, postbox: Postbox,
flags |= Int32(1 << 17)
}
return network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: text, media: inputMedia, replyMarkup: nil, entities: apiEntities, scheduleDate: effectiveScheduleTime, scheduleRepeatPeriod: effectiveScheduleRepeatPeriod, quickReplyShortcutId: quickReplyShortcutId))
return network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: text, media: inputMedia, replyMarkup: nil, entities: apiEntities, scheduleDate: effectiveScheduleTime, scheduleRepeatPeriod: effectiveScheduleRepeatPeriod, quickReplyShortcutId: quickReplyShortcutId, richMessage: apiRichMessage))
|> map { result -> Api.Updates? in
return result
}
@ -429,7 +435,7 @@ func _internal_requestEditLiveLocation(postbox: Postbox, network: Network, state
inputMedia = .inputMediaGeoLive(.init(flags: 1 << 0, geoPoint: .inputGeoPoint(.init(flags: 0, lat: media.latitude, long: media.longitude, accuracyRadius: nil)), heading: nil, period: nil, proximityNotificationRadius: nil))
}
return network.request(Api.functions.messages.editMessage(flags: 1 << 14, peer: inputPeer, id: messageId.id, message: nil, media: inputMedia, replyMarkup: nil, entities: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, quickReplyShortcutId: nil))
return network.request(Api.functions.messages.editMessage(flags: 1 << 14, peer: inputPeer, id: messageId.id, message: nil, media: inputMedia, replyMarkup: nil, entities: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, quickReplyShortcutId: nil, richMessage: nil))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)

View file

@ -366,6 +366,7 @@ private func sendUploadedMessageContent(
var uniqueId: Int64 = 0
var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var messageEntities: [Api.MessageEntity]?
var apiRichMessage: Api.InputRichMessage?
var replyMessageId: Int32?
var topMsgId: Int32?
var monoforumPeerId: Api.InputPeer?
@ -442,6 +443,9 @@ private func sendUploadedMessageContent(
allowPaidStars = attribute.stars.value
} else if let attribute = attribute as? SuggestedPostMessageAttribute {
suggestedPost = attribute.apiSuggestedPost(fixMinTime: Int32(Date().timeIntervalSince1970 + 10))
} else if let attribute = attribute as? RichTextMessageAttribute {
apiRichMessage = attribute.apiInputRichMessage()
flags |= Int32(1 << 23)
}
}
@ -512,7 +516,7 @@ private func sendUploadedMessageContent(
flags |= 1 << 22
}
sendMessageRequest = network.requestWithAdditionalInfo(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), info: .acknowledgement, tag: dependencyTag)
sendMessageRequest = network.requestWithAdditionalInfo(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost, richMessage: apiRichMessage), info: .acknowledgement, tag: dependencyTag)
case let .media(inputMedia, text):
if bubbleUpEmojiOrStickersets {
flags |= Int32(1 << 15)
@ -692,6 +696,7 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
var uniqueId: Int64 = Int64.random(in: Int64.min ... Int64.max)
//var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var messageEntities: [Api.MessageEntity]?
var apiRichMessage: Api.InputRichMessage?
var replyMessageId: Int32?
var replyToStoryId: StoryId?
var scheduleTime: Int32?
@ -731,6 +736,9 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
allowPaidStars = attribute.stars.value
} else if let attribute = attribute as? SuggestedPostMessageAttribute {
suggestedPost = attribute.apiSuggestedPost(fixMinTime: Int32(Date().timeIntervalSince1970 + 10))
} else if let attribute = attribute as? RichTextMessageAttribute {
apiRichMessage = attribute.apiInputRichMessage()
flags |= Int32(1 << 23)
}
}
@ -767,7 +775,7 @@ private func sendMessageContent(account: Account, peerId: PeerId, attributes: [M
replyTo = .inputReplyToMessage(.init(flags: flags, replyToMsgId: threadId, topMsgId: threadId, replyToPeerId: nil, quoteText: nil, quoteEntities: nil, quoteOffset: nil, monoforumPeerId: nil, todoItemId: nil, pollOption: nil))
}
sendMessageRequest = account.network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, allowPaidStars: allowPaidStars, suggestedPost: nil))
sendMessageRequest = account.network.request(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: nil, effect: nil, allowPaidStars: allowPaidStars, suggestedPost: nil, richMessage: apiRichMessage))
|> `catch` { _ -> Signal<Api.Updates, NoError> in
return .complete()
}

View file

@ -1720,6 +1720,7 @@ public final class PendingMessageManager {
var uniqueId: Int64 = 0
var forwardSourceInfoAttribute: ForwardSourceInfoAttribute?
var messageEntities: [Api.MessageEntity]?
var apiRichMessage: Api.InputRichMessage?
var replyMessageId: Int32?
var replyPeerId: PeerId?
var replyQuote: EngineMessageReplyQuote?
@ -1803,6 +1804,9 @@ public final class PendingMessageManager {
allowPaidStars = attribute.stars.value
} else if let attribute = attribute as? SuggestedPostMessageAttribute {
suggestedPost = attribute.apiSuggestedPost(fixMinTime: Int32(Date().timeIntervalSince1970 + 10))
} else if let attribute = attribute as? RichTextMessageAttribute {
apiRichMessage = attribute.apiInputRichMessage()
flags |= Int32(1 << 23)
}
}
@ -1928,7 +1932,7 @@ public final class PendingMessageManager {
flags |= 1 << 22
}
sendMessageRequest = network.requestWithAdditionalInfo(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, effect: messageEffectId, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost), info: .acknowledgement, tag: dependencyTag)
sendMessageRequest = network.requestWithAdditionalInfo(Api.functions.messages.sendMessage(flags: flags, peer: inputPeer, replyTo: replyTo, message: message.text, randomId: uniqueId, replyMarkup: nil, entities: messageEntities, scheduleDate: scheduleTime, scheduleRepeatPeriod: scheduleRepeatPeriod, sendAs: sendAsInputPeer, quickReplyShortcut: quickReplyShortcut, effect: messageEffectId, allowPaidStars: allowPaidStars, suggestedPost: suggestedPost, richMessage: apiRichMessage), info: .acknowledgement, tag: dependencyTag)
case let .media(inputMedia, text):
if bubbleUpEmojiOrStickersets {
flags |= Int32(1 << 15)

View file

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

View file

@ -62,7 +62,7 @@ class UpdateMessageService: NSObject, MTMessageService {
}
case let .updateShortChatMessage(updateShortChatMessageData):
let (flags, id, fromId, chatId, message, pts, ptsCount, date, fwdFrom, viaBotId, replyHeader, entities, ttlPeriod) = (updateShortChatMessageData.flags, updateShortChatMessageData.id, updateShortChatMessageData.fromId, updateShortChatMessageData.chatId, updateShortChatMessageData.message, updateShortChatMessageData.pts, updateShortChatMessageData.ptsCount, updateShortChatMessageData.date, updateShortChatMessageData.fwdFrom, updateShortChatMessageData.viaBotId, updateShortChatMessageData.replyTo, updateShortChatMessageData.entities, updateShortChatMessageData.ttlPeriod)
let generatedMessage = Api.Message.message(.init(flags: flags, flags2: 0, id: id, fromId: .peerUser(.init(userId: fromId)), fromBoostsApplied: nil, fromRank: nil, peerId: Api.Peer.peerChat(.init(chatId: chatId)), savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, guestchatViaFrom: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil, reportDeliveryUntilDate: nil, paidMessageStars: nil, suggestedPost: nil, scheduleRepeatPeriod: nil, summaryFromLanguage: nil))
let generatedMessage = Api.Message.message(.init(flags: flags, flags2: 0, id: id, fromId: .peerUser(.init(userId: fromId)), fromBoostsApplied: nil, fromRank: nil, peerId: Api.Peer.peerChat(.init(chatId: chatId)), savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, guestchatViaFrom: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil, reportDeliveryUntilDate: nil, paidMessageStars: nil, suggestedPost: nil, scheduleRepeatPeriod: nil, summaryFromLanguage: nil, richMessage: nil))
let update = Api.Update.updateNewMessage(.init(message: generatedMessage, pts: pts, ptsCount: ptsCount))
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
if groups.count != 0 {
@ -79,7 +79,7 @@ class UpdateMessageService: NSObject, MTMessageService {
let generatedPeerId = Api.Peer.peerUser(.init(userId: userId))
let generatedMessage = Api.Message.message(.init(flags: flags, flags2: 0, id: id, fromId: generatedFromId, fromBoostsApplied: nil, fromRank: nil, peerId: generatedPeerId, savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, guestchatViaFrom: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil, reportDeliveryUntilDate: nil, paidMessageStars: nil, suggestedPost: nil, scheduleRepeatPeriod: nil, summaryFromLanguage: nil))
let generatedMessage = Api.Message.message(.init(flags: flags, flags2: 0, id: id, fromId: generatedFromId, fromBoostsApplied: nil, fromRank: nil, peerId: generatedPeerId, savedPeerId: nil, fwdFrom: fwdFrom, viaBotId: viaBotId, viaBusinessBotId: nil, guestchatViaFrom: nil, replyTo: replyHeader, date: date, message: message, media: Api.MessageMedia.messageMediaEmpty, replyMarkup: nil, entities: entities, views: nil, forwards: nil, replies: nil, editDate: nil, postAuthor: nil, groupedId: nil, reactions: nil, restrictionReason: nil, ttlPeriod: ttlPeriod, quickReplyShortcutId: nil, effect: nil, factcheck: nil, reportDeliveryUntilDate: nil, paidMessageStars: nil, suggestedPost: nil, scheduleRepeatPeriod: nil, summaryFromLanguage: nil, richMessage: nil))
let update = Api.Update.updateNewMessage(.init(message: generatedMessage, pts: pts, ptsCount: ptsCount))
let groups = groupUpdates([update], users: [], chats: [], date: date, seqRange: nil)
if groups.count != 0 {

View file

@ -0,0 +1,90 @@
import Foundation
import Postbox
import TelegramApi
public class RichTextMessageAttribute: MessageAttribute, Equatable {
public let instantPage: InstantPage
public var associatedPeerIds: [PeerId] {
/*var result: [PeerId] = []
for entity in entities {
switch entity.type {
case let .TextMention(peerId):
result.append(peerId)
default:
break
}
}
return result*/
return []
}
public var associatedMediaIds: [MediaId] {
/*var result: [MediaId] = []
for entity in self.entities {
switch entity.type {
case let .CustomEmoji(_, fileId):
result.append(MediaId(namespace: Namespaces.Media.CloudFile, id: fileId))
default:
break
}
}
if result.isEmpty {
return result
} else {
return Array(Set(result))
}*/
return []
}
public init(instantPage: InstantPage) {
self.instantPage = instantPage
}
required public init(decoder: PostboxDecoder) {
self.instantPage = decoder.decodeObjectForKey("instantPage", decoder: { InstantPage(decoder: $0) }) as! InstantPage
}
public func encode(_ encoder: PostboxEncoder) {
encoder.encodeObject(self.instantPage, forKey: "instantPage")
}
public static func ==(lhs: RichTextMessageAttribute, rhs: RichTextMessageAttribute) -> Bool {
return lhs.instantPage == rhs.instantPage
}
}
extension RichTextMessageAttribute {
convenience init(apiRichMessage: Api.RichMessage) {
switch apiRichMessage {
case let .richMessage(richMessage):
var media: [MediaId: Media] = [:]
for photo in richMessage.photos {
if let image = telegramMediaImageFromApiPhoto(photo), let id = image.id {
media[id] = image
}
}
for file in richMessage.documents {
if let file = telegramMediaFileFromApiDocument(file, altDocuments: []), let id = file.id {
media[id] = file
}
}
let isRtl = (richMessage.flags & (1 << 0)) != 0
let isPartial = (richMessage.flags & (1 << 1)) != 0
let instantPage = InstantPage(blocks: richMessage.blocks.map({ InstantPageBlock(apiBlock: $0) }), media: media, isComplete: !isPartial, rtl: isRtl, url: "", views: nil)
self.init(instantPage: instantPage)
}
}
func apiInputRichMessage() -> Api.InputRichMessage {
var flags: Int32 = 0
if self.instantPage.rtl {
flags |= (1 << 0)
}
return Api.InputRichMessage.inputRichMessage(Api.InputRichMessage.Cons_inputRichMessage(
flags: flags,
blocks: self.instantPage.blocks.compactMap { $0.apiInputBlock() }
))
}
}

View file

@ -72,6 +72,9 @@ public final class EngineMessage: Equatable {
public var text: String {
return self.impl.text
}
public var richText: RichTextMessageAttribute? {
return self.impl.richText
}
public var attributes: [Attribute] {
return self.impl.attributes
}

View file

@ -270,7 +270,7 @@ func _internal_requestClosePoll(postbox: Postbox, network: Network, stateManager
pollMediaFlags |= 1 << 1
}
return network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: nil, media: .inputMediaPoll(.init(flags: pollMediaFlags, poll: .poll(.init(id: poll.pollId.id, flags: pollFlags, question: .textWithEntities(.init(text: poll.text, entities: apiEntitiesFromMessageTextEntities(poll.textEntities, associatedPeers: SimpleDictionary()))), answers: poll.options.map({ $0.apiOption }), closePeriod: poll.deadlineTimeout, closeDate: poll.deadlineDate, countriesIso2: poll.countries, hash: 0)), correctAnswers: correctAnswersIndices, attachedMedia: nil, solution: mappedSolution, solutionEntities: mappedSolutionEntities, solutionMedia: nil)), replyMarkup: nil, entities: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, quickReplyShortcutId: nil))
return network.request(Api.functions.messages.editMessage(flags: flags, peer: inputPeer, id: messageId.id, message: nil, media: .inputMediaPoll(.init(flags: pollMediaFlags, poll: .poll(.init(id: poll.pollId.id, flags: pollFlags, question: .textWithEntities(.init(text: poll.text, entities: apiEntitiesFromMessageTextEntities(poll.textEntities, associatedPeers: SimpleDictionary()))), answers: poll.options.map({ $0.apiOption }), closePeriod: poll.deadlineTimeout, closeDate: poll.deadlineDate, countriesIso2: poll.countries, hash: 0)), correctAnswers: correctAnswersIndices, attachedMedia: nil, solution: mappedSolution, solutionEntities: mappedSolutionEntities, solutionMedia: nil)), replyMarkup: nil, entities: nil, scheduleDate: nil, scheduleRepeatPeriod: nil, quickReplyShortcutId: nil, richMessage: nil))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.Updates?, NoError> in
return .single(nil)

View file

@ -202,8 +202,8 @@ public extension TelegramEngine {
return _internal_clearAuthorHistory(account: self.account, peerId: peerId, memberId: memberId)
}
public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute? = nil, invertMediaAttribute: InvertMediaMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, invertMediaAttribute: invertMediaAttribute)
public func requestEditMessage(messageId: MessageId, text: String, media: RequestEditMessageMedia, entities: TextEntitiesMessageAttribute?, richText: RichTextMessageAttribute?, inlineStickers: [MediaId: Media], webpagePreviewAttribute: WebpagePreviewMessageAttribute? = nil, invertMediaAttribute: InvertMediaMessageAttribute? = nil, disableUrlPreview: Bool = false, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute? = nil) -> Signal<RequestEditMessageResult, RequestEditMessageError> {
return _internal_requestEditMessage(account: self.account, messageId: messageId, text: text, media: media, entities: entities, richText: richText, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, disableUrlPreview: disableUrlPreview, scheduleInfoAttribute: scheduleInfoAttribute, invertMediaAttribute: invertMediaAttribute)
}
public func requestEditLiveLocation(messageId: MessageId, stop: Bool, coordinate: (latitude: Double, longitude: Double, accuracyRadius: Int32?)?, heading: Int32?, proximityNotificationRadius: Int32?, extendPeriod: Int32?) -> Signal<Void, NoError> {

View file

@ -39,7 +39,7 @@ func _internal_toggleChannelJoinRequest(postbox: Postbox, network: Network, acco
guard let peer = peer, let inputChannel = apiInputChannel(peer) else {
return .fail(.generic)
}
return network.request(Api.functions.channels.toggleJoinRequest(channel: inputChannel, enabled: enabled ? .boolTrue : .boolFalse))
return network.request(Api.functions.channels.toggleJoinRequest(flags: 0, channel: inputChannel, enabled: enabled ? .boolTrue : .boolFalse, guardBot: nil))
|> `catch` { _ -> Signal<Api.Updates, UpdateChannelJoinRequestError> in
return .fail(.generic)
}

View file

@ -18,7 +18,7 @@ func _internal_joinChannel(account: Account, peerId: PeerId, hash: String?) -> S
|> castError(JoinChannelError.self)
|> mapToSignal { peer -> Signal<RenderedChannelParticipant?, JoinChannelError> in
let request: Signal<Api.Updates, MTRpcError>
let request: Signal<Api.messages.ChatInviteJoinResult, MTRpcError>
if let hash = hash {
request = account.network.request(Api.functions.messages.importChatInvite(hash: hash))
} else if let inputChannel = apiInputChannel(peer) {
@ -40,54 +40,57 @@ func _internal_joinChannel(account: Account, peerId: PeerId, hash: String?) -> S
return .generic
}
}
|> mapToSignal { updates -> Signal<RenderedChannelParticipant?, JoinChannelError> in
account.stateManager.addUpdates(updates)
let channels = updates.chats.compactMap { parseTelegramGroupOrChannel(chat: $0) }.compactMap(apiInputChannel)
if let inputChannel = channels.first {
return account.network.request(Api.functions.channels.getParticipant(channel: inputChannel, participant: .inputPeerSelf))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.channels.ChannelParticipant?, JoinChannelError> in
return .single(nil)
}
|> mapToSignal { result -> Signal<RenderedChannelParticipant?, JoinChannelError> in
guard let result = result else {
return .fail(.generic)
|> mapToSignal { result -> Signal<RenderedChannelParticipant?, JoinChannelError> in
switch result {
case let .chatInviteJoinResultOk(result):
account.stateManager.addUpdates(result.updates)
let channels = result.updates.chats.compactMap { parseTelegramGroupOrChannel(chat: $0) }.compactMap(apiInputChannel)
if let inputChannel = channels.first {
return account.network.request(Api.functions.channels.getParticipant(channel: inputChannel, participant: .inputPeerSelf))
|> map(Optional.init)
|> `catch` { _ -> Signal<Api.channels.ChannelParticipant?, JoinChannelError> in
return .single(nil)
}
return account.postbox.transaction { transaction -> RenderedChannelParticipant? in
var peers: [EnginePeer.Id: EnginePeer] = [:]
var presences: [PeerId: PeerPresence] = [:]
guard let peer = transaction.getPeer(account.peerId) else {
return nil
|> mapToSignal { result -> Signal<RenderedChannelParticipant?, JoinChannelError> in
guard let result = result else {
return .fail(.generic)
}
peers[account.peerId] = EnginePeer(peer)
if let presence = transaction.getPeerPresence(peerId: account.peerId) {
presences[account.peerId] = presence
}
let updatedParticipant: ChannelParticipant
switch result {
case let .channelParticipant(channelParticipantData):
let participant = channelParticipantData.participant
updatedParticipant = ChannelParticipant(apiParticipant: participant)
}
if case let .member(_, _, maybeAdminInfo, _, _, _) = updatedParticipant {
if let adminInfo = maybeAdminInfo {
if let peer = transaction.getPeer(adminInfo.promotedBy) {
peers[peer.id] = EnginePeer(peer)
return account.postbox.transaction { transaction -> RenderedChannelParticipant? in
var peers: [EnginePeer.Id: EnginePeer] = [:]
var presences: [PeerId: PeerPresence] = [:]
guard let peer = transaction.getPeer(account.peerId) else {
return nil
}
peers[account.peerId] = EnginePeer(peer)
if let presence = transaction.getPeerPresence(peerId: account.peerId) {
presences[account.peerId] = presence
}
let updatedParticipant: ChannelParticipant
switch result {
case let .channelParticipant(channelParticipantData):
let participant = channelParticipantData.participant
updatedParticipant = ChannelParticipant(apiParticipant: participant)
}
if case let .member(_, _, maybeAdminInfo, _, _, _) = updatedParticipant {
if let adminInfo = maybeAdminInfo {
if let peer = transaction.getPeer(adminInfo.promotedBy) {
peers[peer.id] = EnginePeer(peer)
}
}
}
return RenderedChannelParticipant(participant: updatedParticipant, peer: EnginePeer(peer), peers: peers, presences: presences)
}
return RenderedChannelParticipant(participant: updatedParticipant, peer: EnginePeer(peer), peers: peers, presences: presences)
|> castError(JoinChannelError.self)
}
|> castError(JoinChannelError.self)
} else {
return .fail(.generic)
}
} else {
case .chatInviteJoinResultWebView:
return .fail(.generic)
}
}
|> afterCompleted {
if hash == nil {

View file

@ -80,21 +80,26 @@ func _internal_joinChatInteractively(with hash: String, account: Account) -> Sig
}
}
}
|> mapToSignal { updates -> Signal<PeerId?, JoinLinkError> in
account.stateManager.addUpdates(updates)
if let peerId = apiUpdatesGroups(updates).first?.peerId {
return account.postbox.multiplePeersView([peerId])
|> castError(JoinLinkError.self)
|> filter { view in
return view.peers[peerId] != nil
|> mapToSignal { result -> Signal<PeerId?, JoinLinkError> in
switch result {
case let .chatInviteJoinResultOk(result):
account.stateManager.addUpdates(result.updates)
if let peerId = apiUpdatesGroups(result.updates).first?.peerId {
return account.postbox.multiplePeersView([peerId])
|> castError(JoinLinkError.self)
|> filter { view in
return view.peers[peerId] != nil
}
|> take(1)
|> map { _ in
return peerId
}
|> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .single(nil) |> castError(JoinLinkError.self))
}
|> take(1)
|> map { _ in
return peerId
}
|> timeout(5.0, queue: Queue.concurrentDefaultQueue(), alternate: .single(nil) |> castError(JoinLinkError.self))
return .single(nil)
case .chatInviteJoinResultWebView:
return .fail(.generic)
}
return .single(nil)
}
}

View file

@ -652,6 +652,17 @@ public extension Message {
}
}
public extension Message {
var richText: RichTextMessageAttribute? {
for attribute in self.attributes {
if let attribute = attribute as? RichTextMessageAttribute {
return attribute
}
}
return nil
}
}
public func _internal_parseMediaAttachment(data: Data) -> Media? {
guard let object = Api.parse(Buffer(buffer: MemoryBuffer(data: data))) else {
return nil

View file

@ -383,11 +383,7 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
if let attribute = message.attributes.first(where: { $0 is WebpagePreviewMessageAttribute }) as? WebpagePreviewMessageAttribute, attribute.leadingPreview {
result.insert((message, ChatMessageWebpageBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)), at: addedPriceInfo ? 1 : 0)
} else {
if content.instantPage != nil && item.context.sharedContext.immediateExperimentalUISettings.debugRichText {
result.append((message, ChatMessageRichDataBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
} else {
result.append((message, ChatMessageWebpageBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
}
result.append((message, ChatMessageWebpageBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
}
needReactions = false
}
@ -395,6 +391,18 @@ private func contentNodeMessagesAndClassesForItem(_ item: ChatMessageItem) -> ([
}
}
var richText: RichTextMessageAttribute?
for attribute in item.message.attributes {
if let attribute = attribute as? RichTextMessageAttribute {
richText = attribute
break
}
}
if richText != nil {
result.append((message, ChatMessageRichDataBubbleContentNode.self, itemAttributes, BubbleItemAttributes(isAttachment: false, neighborType: .text, neighborSpacing: .default)))
}
if message.adAttribute != nil {
result.removeAll()
@ -1627,9 +1635,12 @@ public class ChatMessageBubbleItemNode: ChatMessageItemView, ChatMessagePreviewI
let chatLocationPeerId: PeerId = item.chatLocation.peerId ?? item.content.firstMessage.id.peerId
var isInlinePage = false
if item.context.sharedContext.immediateExperimentalUISettings.debugRichText, let webpage = item.message.media.first(where: { $0 is TelegramMediaWebpage }) as? TelegramMediaWebpage, case let .Loaded(content) = webpage.content, content.instantPage != nil {
allowFullWidth = true
isInlinePage = true
for attribute in item.message.attributes {
if attribute is RichTextMessageAttribute {
allowFullWidth = true
isInlinePage = true
break
}
}
do {

View file

@ -463,7 +463,7 @@ public class ChatMessageRichDataBubbleContentNode: ChatMessageBubbleContentNode
let pageView = self.ensurePageView()
pageView.update(layout: pageLayout, theme: pageTheme, animation: animation)
pageView.frame = CGRect(
origin: .zero,
origin: CGPoint(x: -1.0, y: 0.0),
size: pageLayout.contentSize
)
} else {

View file

@ -2292,7 +2292,7 @@ extension ChatControllerImpl {
let currentWebpagePreviewAttribute = currentMessage.webpagePreviewAttribute ?? WebpagePreviewMessageAttribute(leadingPreview: false, forceLargeMedia: nil, isManuallyAdded: true, isSafe: false)
if currentMessage.text != text.string || currentEntities != entities || updatingMedia || webpagePreviewAttribute != currentWebpagePreviewAttribute || disableUrlPreview {
strongSelf.context.account.pendingUpdateMessageManager.add(messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertedMediaAttribute, disableUrlPreview: disableUrlPreview)
strongSelf.context.account.pendingUpdateMessageManager.add(messageId: editMessage.messageId, text: text.string, media: media, entities: entitiesAttribute, richText: nil, inlineStickers: inlineStickers, webpagePreviewAttribute: webpagePreviewAttribute, invertMediaAttribute: invertedMediaAttribute, disableUrlPreview: disableUrlPreview)
}
}

View file

@ -231,6 +231,7 @@ extension ChatControllerImpl {
text: "",
media: .update(.standalone(media: updatedTodo)),
entities: nil,
richText: nil,
inlineStickers: [:]
).start()
})))

View file

@ -4175,13 +4175,15 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
strongSelf.presentScheduleTimePicker(selectedTime: message.timestamp, selectedRepeatPeriod: message._asMessage().scheduleRepeatPeriod, completion: { [weak self] time, repeatPeriod in
if let strongSelf = self {
var entities: TextEntitiesMessageAttribute?
var richText: RichTextMessageAttribute?
for attribute in message.attributes {
if let attribute = attribute as? TextEntitiesMessageAttribute {
entities = attribute
break
} else if let attribute = attribute as? RichTextMessageAttribute {
richText = attribute
}
}
strongSelf.editMessageDisposable.set((strongSelf.context.engine.messages.requestEditMessage(messageId: messageId, text: message.text, media: .keep, entities: entities, inlineStickers: [:], webpagePreviewAttribute: nil, disableUrlPreview: false, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute(scheduleTime: time, repeatPeriod: repeatPeriod)) |> deliverOnMainQueue).startStrict(next: { result in
strongSelf.editMessageDisposable.set((strongSelf.context.engine.messages.requestEditMessage(messageId: messageId, text: message.text, media: .keep, entities: entities, richText: richText, inlineStickers: [:], webpagePreviewAttribute: nil, disableUrlPreview: false, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute(scheduleTime: time, repeatPeriod: repeatPeriod)) |> deliverOnMainQueue).startStrict(next: { result in
}, error: { error in
}))
}

View file

@ -519,14 +519,16 @@ extension ChatControllerImpl {
return
}
var entities: TextEntitiesMessageAttribute?
var richText: RichTextMessageAttribute?
for attribute in message.attributes {
if let attribute = attribute as? TextEntitiesMessageAttribute {
entities = attribute
break
} else if let attribute = attribute as? RichTextMessageAttribute {
richText = attribute
}
}
let scheduleTime = message.timestamp + repeatAttribute.repeatPeriod
self.editMessageDisposable.set((self.context.engine.messages.requestEditMessage(messageId: message.id, text: message.text, media: .keep, entities: entities, inlineStickers: [:], webpagePreviewAttribute: nil, disableUrlPreview: false, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute(scheduleTime: scheduleTime, repeatPeriod: repeatAttribute.repeatPeriod)) |> deliverOnMainQueue).startStrict(next: { result in
self.editMessageDisposable.set((self.context.engine.messages.requestEditMessage(messageId: message.id, text: message.text, media: .keep, entities: entities, richText: richText, inlineStickers: [:], webpagePreviewAttribute: nil, disableUrlPreview: false, scheduleInfoAttribute: OutgoingScheduleInfoMessageAttribute(scheduleTime: scheduleTime, repeatPeriod: repeatAttribute.repeatPeriod)) |> deliverOnMainQueue).startStrict(next: { result in
}, error: { error in
}))
}),

View file

@ -67,6 +67,7 @@ import PresentationDataUtils
import TextProcessingScreen
import Pasteboard
import UndoUI
import BrowserUI
final class VideoNavigationControllerDropContentItem: NavigationControllerDropContentItem {
let itemNode: OverlayMediaItemNode
@ -4856,44 +4857,51 @@ class ChatControllerNode: ASDisplayNode, ASScrollViewDelegate {
}
}
for text in breakChatInputText(trimChatInputText(inputText)) {
if text.length != 0 {
var attributes: [MessageAttribute] = []
let entities: [MessageTextEntity]
if case let .customChatContents(customChatContents) = self.chatPresentationInterfaceState.subject, case .businessLinkSetup = customChatContents.kind {
entities = generateChatInputTextEntities(text, generateLinks: false)
} else {
entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text, maxAnimatedEmojisInText: 0))
}
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
if let urlPreview = self.chatPresentationInterfaceState.urlPreview {
if self.chatPresentationInterfaceState.interfaceState.composeDisableUrlPreviews.contains(urlPreview.url) {
attributes.append(OutgoingContentInfoMessageAttribute(flags: [.disableLinkPreviews]))
if self.context.sharedContext.immediateExperimentalUISettings.debugRichText, let attribute = inputRichTextAttributeFromText(context: self.context, text: inputText.string) {
var attributes: [MessageAttribute] = []
attributes.append(attribute)
messages.append(.message(text: "", attributes: attributes, inlineStickers: [:], mediaReference: nil, threadId: self.chatLocation.threadId, replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: []))
mediaReference = nil
} else {
for text in breakChatInputText(trimChatInputText(inputText)) {
if text.length != 0 {
var attributes: [MessageAttribute] = []
let entities: [MessageTextEntity]
if case let .customChatContents(customChatContents) = self.chatPresentationInterfaceState.subject, case .businessLinkSetup = customChatContents.kind {
entities = generateChatInputTextEntities(text, generateLinks: false)
} else {
attributes.append(WebpagePreviewMessageAttribute(leadingPreview: !urlPreview.positionBelowText, forceLargeMedia: urlPreview.largeMedia, isManuallyAdded: true, isSafe: false))
entities = generateTextEntities(text.string, enabledTypes: .all, currentEntities: generateChatInputTextEntities(text, maxAnimatedEmojisInText: 0))
}
}
var bubbleUpEmojiOrStickersets: [ItemCollectionId] = []
for entity in entities {
if case let .CustomEmoji(_, fileId) = entity.type {
if let packId = bubbleUpEmojiOrStickersetsById[fileId] {
if !bubbleUpEmojiOrStickersets.contains(packId) {
bubbleUpEmojiOrStickersets.append(packId)
if !entities.isEmpty {
attributes.append(TextEntitiesMessageAttribute(entities: entities))
}
if let urlPreview = self.chatPresentationInterfaceState.urlPreview {
if self.chatPresentationInterfaceState.interfaceState.composeDisableUrlPreviews.contains(urlPreview.url) {
attributes.append(OutgoingContentInfoMessageAttribute(flags: [.disableLinkPreviews]))
} else {
attributes.append(WebpagePreviewMessageAttribute(leadingPreview: !urlPreview.positionBelowText, forceLargeMedia: urlPreview.largeMedia, isManuallyAdded: true, isSafe: false))
}
}
var bubbleUpEmojiOrStickersets: [ItemCollectionId] = []
for entity in entities {
if case let .CustomEmoji(_, fileId) = entity.type {
if let packId = bubbleUpEmojiOrStickersetsById[fileId] {
if !bubbleUpEmojiOrStickersets.contains(packId) {
bubbleUpEmojiOrStickersets.append(packId)
}
}
}
}
if bubbleUpEmojiOrStickersets.count > 1 {
bubbleUpEmojiOrStickersets.removeAll()
}
messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, threadId: self.chatLocation.threadId, replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
mediaReference = nil
}
if bubbleUpEmojiOrStickersets.count > 1 {
bubbleUpEmojiOrStickersets.removeAll()
}
messages.append(.message(text: text.string, attributes: attributes, inlineStickers: inlineStickers, mediaReference: mediaReference, threadId: self.chatLocation.threadId, replyToMessageId: self.chatPresentationInterfaceState.interfaceState.replyMessageSubject?.subjectModel, replyToStoryId: nil, localGroupingKey: nil, correlationId: nil, bubbleUpEmojiOrStickersets: bubbleUpEmojiOrStickersets))
mediaReference = nil
}
}

View file

@ -2257,6 +2257,7 @@ extension ChatControllerImpl {
text: "",
media: .update(.standalone(media: todo)),
entities: nil,
richText: nil,
inlineStickers: [:]
).start()
} else {