Merge commit '057a7cc148fb77bcb8f58b8135c8ccb99725b5d4'

This commit is contained in:
Ali 2022-01-11 23:34:55 +04:00
commit 1831f1e84b
24 changed files with 221 additions and 56 deletions

Binary file not shown.

View File

@ -535,7 +535,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} else { } else {
result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage
} }
let (_, initialHideAuthor, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false) let (_, initialHideAuthor, messageText, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author { if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author {
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)" result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
} }
@ -569,7 +569,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} else { } else {
result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage result += item.presentationData.strings.VoiceOver_ChatList_OutgoingMessage
} }
let (_, initialHideAuthor, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false) let (_, initialHideAuthor, messageText, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: peer, accountPeerId: item.context.account.peerId, isPeerGroup: false)
if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author { if message.flags.contains(.Incoming), !initialHideAuthor, let author = message.author, case .user = author {
result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)" result += "\n\(item.presentationData.strings.VoiceOver_ChatList_MessageFrom(author.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)).string)"
} }
@ -965,7 +965,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
let leftInset: CGFloat = params.leftInset + avatarLeftInset let leftInset: CGFloat = params.leftInset + avatarLeftInset
enum ContentData { enum ContentData {
case chat(itemPeer: EngineRenderedPeer, peer: EnginePeer?, hideAuthor: Bool, messageText: String) case chat(itemPeer: EngineRenderedPeer, peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?)
case group(peers: [EngineChatList.GroupItem.Item]) case group(peers: [EngineChatList.GroupItem.Item])
} }
@ -974,14 +974,14 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
var hideAuthor = false var hideAuthor = false
switch contentPeer { switch contentPeer {
case let .chat(itemPeer): case let .chat(itemPeer):
var (peer, initialHideAuthor, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: itemPeer, accountPeerId: item.context.account.peerId, enableMediaEmoji: !enableChatListPhotos, isPeerGroup: isPeerGroup) var (peer, initialHideAuthor, messageText, spoilers) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: messages, chatPeer: itemPeer, accountPeerId: item.context.account.peerId, enableMediaEmoji: !enableChatListPhotos, isPeerGroup: isPeerGroup)
if case let .psa(_, maybePsaText) = promoInfo, let psaText = maybePsaText { if case let .psa(_, maybePsaText) = promoInfo, let psaText = maybePsaText {
initialHideAuthor = true initialHideAuthor = true
messageText = psaText messageText = psaText
} }
contentData = .chat(itemPeer: itemPeer, peer: peer, hideAuthor: hideAuthor, messageText: messageText) contentData = .chat(itemPeer: itemPeer, peer: peer, hideAuthor: hideAuthor, messageText: messageText, spoilers: spoilers)
hideAuthor = initialHideAuthor hideAuthor = initialHideAuthor
case let .group(groupPeers): case let .group(groupPeers):
contentData = .group(peers: groupPeers) contentData = .group(peers: groupPeers)
@ -1012,7 +1012,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
var contentImageSpecs: [(message: EngineMessage, media: EngineMedia, size: CGSize)] = [] var contentImageSpecs: [(message: EngineMessage, media: EngineMedia, size: CGSize)] = []
switch contentData { switch contentData {
case let .chat(itemPeer, _, _, text): case let .chat(itemPeer, _, _, text, spoilers):
var isUser = false var isUser = false
if case .user = itemPeer.chatMainPeer { if case .user = itemPeer.chatMainPeer {
isUser = true isUser = true
@ -1039,7 +1039,11 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
messageText = currentChatListText.1 messageText = currentChatListText.1
chatListText = currentChatListText chatListText = currentChatListText
} else { } else {
messageText = foldLineBreaks(text) if let spoilers = spoilers, !spoilers.isEmpty {
messageText = text
} else {
messageText = foldLineBreaks(text)
}
chatListText = (text, messageText) chatListText = (text, messageText)
} }
@ -1053,6 +1057,10 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} else if let message = messages.last { } else if let message = messages.last {
var composedString: NSMutableAttributedString var composedString: NSMutableAttributedString
if let peerText = peerText {
authorAttributedString = NSAttributedString(string: peerText, font: textFont, textColor: theme.authorNameColor)
}
let entities = (message._asMessage().textEntitiesAttribute?.entities ?? []).filter { entity in let entities = (message._asMessage().textEntitiesAttribute?.entities ?? []).filter { entity in
if case .Spoiler = entity.type { if case .Spoiler = entity.type {
return true return true
@ -1062,7 +1070,13 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} }
let messageString: NSAttributedString let messageString: NSAttributedString
if !message.text.isEmpty && entities.count > 0 { if !message.text.isEmpty && entities.count > 0 {
messageString = stringWithAppliedEntities(message.text, entities: entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) messageString = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: authorAttributedString == nil ? 2 : 1), entities: entities, baseColor: theme.messageTextColor, linkColor: theme.messageTextColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false)
} else if let spoilers = spoilers {
let mutableString = NSMutableAttributedString(string: messageText, font: textFont, textColor: theme.messageTextColor)
for range in spoilers {
mutableString.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler), value: true, range: range)
}
messageString = mutableString
} else { } else {
messageString = NSAttributedString(string: messageText, font: textFont, textColor: theme.messageTextColor) messageString = NSAttributedString(string: messageText, font: textFont, textColor: theme.messageTextColor)
} }
@ -1109,9 +1123,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
attributedText = composedString attributedText = composedString
if let peerText = peerText {
authorAttributedString = NSAttributedString(string: peerText, font: textFont, textColor: theme.authorNameColor)
}
var displayMediaPreviews = true var displayMediaPreviews = true
if message._asMessage().containsSecretMedia { if message._asMessage().containsSecretMedia {
@ -1202,7 +1214,7 @@ class ChatListItemNode: ItemListRevealOptionsItemNode {
} }
switch contentData { switch contentData {
case let .chat(itemPeer, _, _, _): case let .chat(itemPeer, _, _, _, _):
if let message = messages.last, case let .user(author) = message.author, displayAsMessage { if let message = messages.last, case let .user(author) = message.author, displayAsMessage {
titleAttributedString = NSAttributedString(string: author.id == account.peerId ? item.presentationData.strings.DialogList_You : EnginePeer.user(author).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder), font: titleFont, textColor: theme.titleColor) titleAttributedString = NSAttributedString(string: author.id == account.peerId ? item.presentationData.strings.DialogList_You : EnginePeer.user(author).displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder), font: titleFont, textColor: theme.titleColor)
} else if isPeerGroup { } else if isPeerGroup {

View File

@ -44,13 +44,14 @@ private func messageGroupType(messages: [EngineMessage]) -> MessageGroupType {
return currentType return currentType
} }
public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, messages: [EngineMessage], chatPeer: EngineRenderedPeer, accountPeerId: EnginePeer.Id, enableMediaEmoji: Bool = true, isPeerGroup: Bool = false) -> (peer: EnginePeer?, hideAuthor: Bool, messageText: String) { public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, messages: [EngineMessage], chatPeer: EngineRenderedPeer, accountPeerId: EnginePeer.Id, enableMediaEmoji: Bool = true, isPeerGroup: Bool = false) -> (peer: EnginePeer?, hideAuthor: Bool, messageText: String, spoilers: [NSRange]?) {
let peer: EnginePeer? let peer: EnginePeer?
let message = messages.last let message = messages.last
var hideAuthor = false var hideAuthor = false
var messageText: String var messageText: String
var spoilers: [NSRange]?
if let message = message { if let message = message {
if let messageMain = messageMainPeer(message) { if let messageMain = messageMainPeer(message) {
peer = messageMain peer = messageMain
@ -268,12 +269,13 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
} }
default: default:
hideAuthor = true hideAuthor = true
if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { if let (text, textSpoilers) = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) {
messageText = text messageText = text
spoilers = textSpoilers
} }
} }
case _ as TelegramMediaExpiredContent: case _ as TelegramMediaExpiredContent:
if let text = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) { if let (text, _) = plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: true) {
messageText = text messageText = text
} }
case let poll as TelegramMediaPoll: case let poll as TelegramMediaPoll:
@ -312,5 +314,5 @@ public func chatListItemStrings(strings: PresentationStrings, nameDisplayOrder:
} }
} }
return (peer, hideAuthor, messageText) return (peer, hideAuthor, messageText, spoilers)
} }

View File

@ -409,8 +409,15 @@ open class NavigationController: UINavigationController, ContainableController,
let overlayContainerLayout = layout let overlayContainerLayout = layout
if let inCallStatusBar = self.inCallStatusBar { if let inCallStatusBar = self.inCallStatusBar {
var inCallStatusBarFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(layout.statusBarHeight ?? 0.0, max(40.0, layout.safeInsets.top)))) let isLandscape = layout.size.width > layout.size.height
if layout.deviceMetrics.hasTopNotch { var minHeight: CGFloat
if case .compact = layout.metrics.widthClass, isLandscape {
minHeight = 22.0
} else {
minHeight = 40.0
}
var inCallStatusBarFrame = CGRect(origin: CGPoint(), size: CGSize(width: layout.size.width, height: max(layout.statusBarHeight ?? 0.0, max(minHeight, layout.safeInsets.top))))
if layout.deviceMetrics.hasTopNotch && !isLandscape {
inCallStatusBarFrame.size.height += 12.0 inCallStatusBarFrame.size.height += 12.0
} }
if inCallStatusBar.frame.isEmpty { if inCallStatusBar.frame.isEmpty {

View File

@ -182,10 +182,12 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer
} }
func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) { func updateLayout(size: CGSize, isLandscape: Bool, bottomInset: CGFloat, transition: ContainedViewLayoutTransition) {
var nodeHeight: CGFloat = (self.peerNodes.isEmpty ? 264.0 : 364.0) let showPeers = !self.peerNodes.isEmpty && !isLandscape
var nodeHeight: CGFloat = (!showPeers ? 236.0 : 320.0)
let paddedSize = CGSize(width: size.width - 60.0, height: size.height) let paddedSize = CGSize(width: size.width - 60.0, height: size.height)
self.peersScrollNode.isHidden = !showPeers
var aboutSize: CGSize? var aboutSize: CGSize?
var descriptionSize: CGSize? var descriptionSize: CGSize?
if self.aboutNode.supernode != nil { if self.aboutNode.supernode != nil {
@ -210,14 +212,16 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer
descriptionSize = measuredSize descriptionSize = measuredSize
} }
let constrainSize = CGSize(width: size.width - 32.0, height: size.height)
let titleSize = self.titleNode.measure(constrainSize)
nodeHeight += titleSize.height
let verticalOrigin = size.height - nodeHeight let verticalOrigin = size.height - nodeHeight
let avatarSize: CGFloat = 100.0 let avatarSize: CGFloat = 100.0
transition.updateFrame(node: self.avatarNode, frame: CGRect(origin: CGPoint(x: floor((size.width - avatarSize) / 2.0), y: verticalOrigin + 32.0), size: CGSize(width: avatarSize, height: avatarSize))) transition.updateFrame(node: self.avatarNode, frame: CGRect(origin: CGPoint(x: floor((size.width - avatarSize) / 2.0), y: verticalOrigin + 32.0), size: CGSize(width: avatarSize, height: avatarSize)))
let constrainSize = CGSize(width: size.width - 32.0, height: size.height)
let titleSize = self.titleNode.measure(constrainSize)
transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: verticalOrigin + 27.0 + avatarSize + 15.0), size: titleSize)) transition.updateFrame(node: self.titleNode, frame: CGRect(origin: CGPoint(x: floor((size.width - titleSize.width) / 2.0), y: verticalOrigin + 27.0 + avatarSize + 15.0), size: titleSize))
let countSize = self.countNode.measure(constrainSize) let countSize = self.countNode.measure(constrainSize)
@ -246,9 +250,9 @@ final class JoinLinkPreviewPeerContentNode: ASDisplayNode, ShareContentContainer
} }
self.peersScrollNode.view.contentSize = CGSize(width: CGFloat(self.peerNodes.count) * peerSize.width + (self.moreNode != nil ? peerSize.width : 0.0) + peerInset * 2.0, height: peerSize.height) self.peersScrollNode.view.contentSize = CGSize(width: CGFloat(self.peerNodes.count) * peerSize.width + (self.moreNode != nil ? peerSize.width : 0.0) + peerInset * 2.0, height: peerSize.height)
transition.updateFrame(node: self.peersScrollNode, frame: CGRect(origin: CGPoint(x: 0.0, y: verticalOrigin + 210.0), size: CGSize(width: size.width, height: peerSize.height))) transition.updateFrame(node: self.peersScrollNode, frame: CGRect(origin: CGPoint(x: 0.0, y: verticalOrigin + 27.0 + avatarSize + 15.0 + titleSize.height + 3.0 + countSize.height + 12.0), size: CGSize(width: size.width, height: peerSize.height)))
if !self.peerNodes.isEmpty { if showPeers {
verticalOffset += 100.0 verticalOffset += 100.0
} }

View File

@ -95,6 +95,8 @@ swift_library(
"//submodules/Components/ReactionImageComponent:ReactionImageComponent", "//submodules/Components/ReactionImageComponent:ReactionImageComponent",
"//submodules/Translate:Translate", "//submodules/Translate:Translate",
"//submodules/QrCodeUI:QrCodeUI", "//submodules/QrCodeUI:QrCodeUI",
"//submodules/AnimatedStickerNode:AnimatedStickerNode",
"//submodules/TelegramAnimatedStickerNode:TelegramAnimatedStickerNode",
], ],
visibility = [ visibility = [
"//visibility:public", "//visibility:public",

View File

@ -13,6 +13,15 @@ enum PrivacyIntroControllerMode {
case passcode case passcode
case twoStepVerification case twoStepVerification
var animationName: String? {
switch self {
case .passcode:
return "Passcode"
case .twoStepVerification:
return nil
}
}
func icon(theme: PresentationTheme) -> UIImage? { func icon(theme: PresentationTheme) -> UIImage? {
switch self { switch self {
case .passcode: case .passcode:

View File

@ -8,6 +8,8 @@ import SwiftSignalKit
import TelegramPresentationData import TelegramPresentationData
import AccountContext import AccountContext
import AuthorizationUI import AuthorizationUI
import AnimatedStickerNode
import TelegramAnimatedStickerNode
private func generateButtonImage(backgroundColor: UIColor, highlightColor: UIColor?) -> UIImage? { private func generateButtonImage(backgroundColor: UIColor, highlightColor: UIColor?) -> UIImage? {
return generateImage(CGSize(width: 24.0, height: 44.0), contextGenerator: { size, context in return generateImage(CGSize(width: 24.0, height: 44.0), contextGenerator: { size, context in
@ -39,6 +41,7 @@ final class PrivacyIntroControllerNode: ViewControllerTracingNode {
private let proceedAction: () -> Void private let proceedAction: () -> Void
private let iconNode: ASImageNode private let iconNode: ASImageNode
private let animationNode: AnimatedStickerNode
private let titleNode: ASTextNode private let titleNode: ASTextNode
private let textNode: ASTextNode private let textNode: ASTextNode
private let buttonNode: HighlightTrackingButtonNode private let buttonNode: HighlightTrackingButtonNode
@ -55,6 +58,8 @@ final class PrivacyIntroControllerNode: ViewControllerTracingNode {
self.proceedAction = proceedAction self.proceedAction = proceedAction
self.iconNode = ASImageNode() self.iconNode = ASImageNode()
self.animationNode = AnimatedStickerNode()
self.titleNode = ASTextNode() self.titleNode = ASTextNode()
self.textNode = ASTextNode() self.textNode = ASTextNode()
self.buttonNode = HighlightTrackingButtonNode() self.buttonNode = HighlightTrackingButtonNode()
@ -68,7 +73,19 @@ final class PrivacyIntroControllerNode: ViewControllerTracingNode {
super.init() super.init()
if let animationName = mode.animationName {
self.iconNode.isHidden = true
self.animationNode.isHidden = false
self.animationNode.setup(source: AnimatedStickerNodeLocalFileSource(name: animationName), width: 380, height: 380, playbackMode: .loop, mode: .direct(cachePathPrefix: nil))
self.animationNode.visibility = true
} else {
self.iconNode.isHidden = false
self.animationNode.isHidden = true
}
self.addSubnode(self.iconNode) self.addSubnode(self.iconNode)
self.addSubnode(self.animationNode)
self.addSubnode(self.titleNode) self.addSubnode(self.titleNode)
self.addSubnode(self.textNode) self.addSubnode(self.textNode)
self.addSubnode(self.buttonBackgroundNode) self.addSubnode(self.buttonBackgroundNode)
@ -98,7 +115,9 @@ final class PrivacyIntroControllerNode: ViewControllerTracingNode {
self.presentationData = presentationData self.presentationData = presentationData
self.backgroundColor = presentationData.theme.list.blocksBackgroundColor self.backgroundColor = presentationData.theme.list.blocksBackgroundColor
self.iconNode.image = self.mode.icon(theme: presentationData.theme) if self.animationNode.isHidden {
self.iconNode.image = self.mode.icon(theme: presentationData.theme)
}
self.titleNode.attributedText = NSAttributedString(string: self.mode.title(strings: presentationData.strings), font: titleFont, textColor: presentationData.theme.list.sectionHeaderTextColor, paragraphAlignment: .center) self.titleNode.attributedText = NSAttributedString(string: self.mode.title(strings: presentationData.strings), font: titleFont, textColor: presentationData.theme.list.sectionHeaderTextColor, paragraphAlignment: .center)
self.textNode.attributedText = NSAttributedString(string: self.mode.text(strings: presentationData.strings), font: textFont, textColor: presentationData.theme.list.freeTextColor, paragraphAlignment: .center) self.textNode.attributedText = NSAttributedString(string: self.mode.text(strings: presentationData.strings), font: textFont, textColor: presentationData.theme.list.freeTextColor, paragraphAlignment: .center)
self.noticeNode.attributedText = NSAttributedString(string: self.mode.notice(strings: presentationData.strings), font: textFont, textColor: presentationData.theme.list.freeTextColor, paragraphAlignment: .center) self.noticeNode.attributedText = NSAttributedString(string: self.mode.notice(strings: presentationData.strings), font: textFont, textColor: presentationData.theme.list.freeTextColor, paragraphAlignment: .center)
@ -120,7 +139,18 @@ final class PrivacyIntroControllerNode: ViewControllerTracingNode {
insets.top += navigationBarHeight insets.top += navigationBarHeight
var iconSize = CGSize() var iconSize = CGSize()
if let size = self.iconNode.image?.size { var animationSize = CGSize()
if !self.animationNode.isHidden {
animationSize = CGSize(width: 180.0, height: 180.0)
self.animationNode.updateLayout(size: animationSize)
var iconAlpha: CGFloat = 1.0
if case .compact = layout.metrics.widthClass, layout.size.width > layout.size.height {
iconAlpha = 0.0
iconSize = CGSize()
}
transition.updateAlpha(node: self.animationNode, alpha: iconAlpha)
} else if let size = self.iconNode.image?.size {
iconSize = size iconSize = size
var iconAlpha: CGFloat = 1.0 var iconAlpha: CGFloat = 1.0
@ -142,9 +172,10 @@ final class PrivacyIntroControllerNode: ViewControllerTracingNode {
} else { } else {
buttonInset = 0.0 buttonInset = 0.0
} }
let items: [AuthorizationLayoutItem] = [ let items: [AuthorizationLayoutItem] = [
AuthorizationLayoutItem(node: self.iconNode, size: iconSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)), AuthorizationLayoutItem(node: self.iconNode, size: iconSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)),
AuthorizationLayoutItem(node: self.animationNode, size: animationSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)),
AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 20.0, maxValue: 30.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)), AuthorizationLayoutItem(node: self.titleNode, size: titleSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 20.0, maxValue: 30.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)),
AuthorizationLayoutItem(node: self.textNode, size: textSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 16.0, maxValue: 16.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)), AuthorizationLayoutItem(node: self.textNode, size: textSize, spacingBefore: AuthorizationLayoutItemSpacing(weight: 16.0, maxValue: 16.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)),
AuthorizationLayoutItem(node: self.buttonNode, size: CGSize(width: layout.size.width - buttonInset * 2.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 40.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)), AuthorizationLayoutItem(node: self.buttonNode, size: CGSize(width: layout.size.width - buttonInset * 2.0, height: 44.0), spacingBefore: AuthorizationLayoutItemSpacing(weight: 40.0, maxValue: 40.0), spacingAfter: AuthorizationLayoutItemSpacing(weight: 0.0, maxValue: 0.0)),

View File

@ -200,17 +200,17 @@ private final class CallVideoNode: ASDisplayNode, PreviewVideoNode {
case .rotation90: case .rotation90:
rotationAngle = CGFloat.pi / 2.0 rotationAngle = CGFloat.pi / 2.0
case .rotation180: case .rotation180:
if isCompactLayout { // if isCompactLayout {
rotationAngle = CGFloat.pi rotationAngle = CGFloat.pi
} else { // } else {
rotationAngle = 0.0 // rotationAngle = 0.0
} // }
case .rotation270: case .rotation270:
if isCompactLayout { // if isCompactLayout {
rotationAngle = -CGFloat.pi / 2.0 rotationAngle = -CGFloat.pi / 2.0
} else { // } else {
rotationAngle = CGFloat.pi / 2.0 // rotationAngle = CGFloat.pi / 2.0
} // }
} }
var additionalAngle: CGFloat = 0.0 var additionalAngle: CGFloat = 0.0

View File

@ -165,7 +165,7 @@ public func mediaContentKind(_ media: EngineMedia, message: EngineMessage? = nil
} }
case .action: case .action:
if let message = message, let strings = strings, let nameDisplayOrder = nameDisplayOrder, let accountPeerId = accountPeerId { if let message = message, let strings = strings, let nameDisplayOrder = nameDisplayOrder, let accountPeerId = accountPeerId {
return .text(plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat ?? PresentationDateTimeFormat(timeFormat: .military, dateFormat: .dayFirst, dateSeparator: ".", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: ""), message: message, accountPeerId: accountPeerId, forChatList: false) ?? "") return .text(plainServiceMessageString(strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat ?? PresentationDateTimeFormat(timeFormat: .military, dateFormat: .dayFirst, dateSeparator: ".", dateSuffix: "", requiresFullYear: false, decimalSeparator: ".", groupingSeparator: ""), message: message, accountPeerId: accountPeerId, forChatList: false)?.0 ?? "")
} else { } else {
return nil return nil
} }
@ -253,3 +253,20 @@ public func foldLineBreaks(_ text: String) -> String {
} }
return result return result
} }
public func trimToLineCount(_ text: String, lineCount: Int) -> String {
if lineCount < 1 {
return ""
}
let lines = text.split { $0.isNewline }
var result = ""
for line in lines.prefix(lineCount) {
if !result.isEmpty {
result += "\n"
}
result += line
}
return result
}

View File

@ -11,6 +11,10 @@ import Markdown
private let titleFont = Font.regular(13.0) private let titleFont = Font.regular(13.0)
private let titleBoldFont = Font.bold(13.0) private let titleBoldFont = Font.bold(13.0)
private func spoilerAttributes(primaryTextColor: UIColor) -> MarkdownAttributeSet {
return MarkdownAttributeSet(font: titleFont, textColor: primaryTextColor, additionalAttributes: [TelegramTextAttributes.Spoiler: true])
}
private func peerMentionAttributes(primaryTextColor: UIColor, peerId: EnginePeer.Id) -> MarkdownAttributeSet { private func peerMentionAttributes(primaryTextColor: UIColor, peerId: EnginePeer.Id) -> MarkdownAttributeSet {
return MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [TelegramTextAttributes.PeerMention: TelegramPeerMention(peerId: peerId, mention: "")]) return MarkdownAttributeSet(font: titleBoldFont, textColor: primaryTextColor, additionalAttributes: [TelegramTextAttributes.PeerMention: TelegramPeerMention(peerId: peerId, mention: "")])
} }
@ -25,8 +29,18 @@ private func peerMentionsAttributes(primaryTextColor: UIColor, peerIds: [(Int, E
return result return result
} }
public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> String? { public func plainServiceMessageString(strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> (String, [NSRange])? {
return universalServiceMessageString(presentationData: nil, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: forChatList)?.string if let attributedString = universalServiceMessageString(presentationData: nil, strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: message, accountPeerId: accountPeerId, forChatList: forChatList) {
var ranges: [NSRange] = []
attributedString.enumerateAttributes(in: NSRange(location: 0, length: attributedString.length), options: [], using: { attributes, range, _ in
if let _ = attributes[NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler)] {
ranges.append(range)
}
})
return (attributedString.string, ranges)
} else {
return nil
}
} }
public func universalServiceMessageString(presentationData: (PresentationTheme, TelegramWallpaper)?, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> NSAttributedString? { public func universalServiceMessageString(presentationData: (PresentationTheme, TelegramWallpaper)?, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: EngineMessage, accountPeerId: EnginePeer.Id, forChatList: Bool) -> NSAttributedString? {
@ -137,7 +151,7 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
} }
case .pinnedMessageUpdated: case .pinnedMessageUpdated:
enum PinnnedMediaType { enum PinnnedMediaType {
case text(String) case text(String, [MessageTextEntity])
case game case game
case photo case photo
case video case video
@ -160,8 +174,15 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
} }
var type: PinnnedMediaType var type: PinnnedMediaType
if let pinnedMessage = pinnedMessage { if let pinnedMessage = pinnedMessage?._asMessage() {
type = .text(pinnedMessage.text) let entities = (pinnedMessage.textEntitiesAttribute?.entities ?? []).filter { entity in
if case .Spoiler = entity.type {
return true
} else {
return false
}
}
type = .text(pinnedMessage.text, entities)
inner: for media in pinnedMessage.media { inner: for media in pinnedMessage.media {
if media is TelegramMediaGame { if media is TelegramMediaGame {
type = .game type = .game
@ -213,8 +234,13 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
} }
switch type { switch type {
case let .text(text): case let .text(text, entities):
var clippedText = text.replacingOccurrences(of: "\n", with: " ") var clippedText = text
if !entities.isEmpty {
clippedText = trimToLineCount(clippedText, lineCount: 1)
} else {
clippedText = clippedText.replacingOccurrences(of: "\n", with: " ")
}
if clippedText.count > 14 { if clippedText.count > 14 {
clippedText = "\(clippedText[...clippedText.index(clippedText.startIndex, offsetBy: 14)])..." clippedText = "\(clippedText[...clippedText.index(clippedText.startIndex, offsetBy: 14)])..."
} }
@ -224,7 +250,21 @@ public func universalServiceMessageString(presentationData: (PresentationTheme,
} else { } else {
textWithRanges = strings.Notification_PinnedTextMessage(authorName, clippedText) textWithRanges = strings.Notification_PinnedTextMessage(authorName, clippedText)
} }
attributedString = addAttributesToStringWithRanges(textWithRanges._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)]))
let string = textWithRanges._tuple.0
let stringLength = (clippedText as NSString).length
var ranges = textWithRanges._tuple.1
let entityOffset = ranges.first(where: { $0.0 == 1 })?.1.location ?? 0
var attributes = peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])
for entity in entities {
if entity.range.startIndex >= stringLength {
continue
}
let index = ranges.count
ranges.append((ranges.count, NSRange(location: entityOffset + entity.range.startIndex, length: entity.range.count)))
attributes[index] = spoilerAttributes(primaryTextColor: primaryTextColor)
}
attributedString = addAttributesToStringWithRanges((string, ranges), body: bodyAttributes, argumentAttributes: attributes)
case .game: case .game:
attributedString = addAttributesToStringWithRanges(strings.Message_AuthorPinnedGame(authorName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)])) attributedString = addAttributesToStringWithRanges(strings.Message_AuthorPinnedGame(authorName)._tuple, body: bodyAttributes, argumentAttributes: peerMentionsAttributes(primaryTextColor: primaryTextColor, peerIds: [(0, message.author?.id)]))
case .photo: case .photo:

File diff suppressed because one or more lines are too long

View File

@ -3961,7 +3961,9 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
} }
var renderedPeer: RenderedPeer? var renderedPeer: RenderedPeer?
var contactStatus: ChatContactStatus? var contactStatus: ChatContactStatus?
var copyProtectionEnabled: Bool = false
if let peer = peerView.peers[peerView.peerId] { if let peer = peerView.peers[peerView.peerId] {
copyProtectionEnabled = peer.isCopyProtectionEnabled
if let cachedData = peerView.cachedData as? CachedUserData { if let cachedData = peerView.cachedData as? CachedUserData {
contactStatus = ChatContactStatus(canAddContact: !peerView.peerIsContact, canReportIrrelevantLocation: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: nil) contactStatus = ChatContactStatus(canAddContact: !peerView.peerIsContact, canReportIrrelevantLocation: false, peerStatusSettings: cachedData.peerStatusSettings, invitedBy: nil)
} else if let cachedData = peerView.cachedData as? CachedGroupData { } else if let cachedData = peerView.cachedData as? CachedGroupData {
@ -4087,6 +4089,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
return $0.updatedPeer { _ in return $0.updatedPeer { _ in
return renderedPeer return renderedPeer
}.updatedIsNotAccessible(isNotAccessible).updatedContactStatus(contactStatus).updatedHasBots(hasBots).updatedIsArchived(isArchived).updatedPeerIsMuted(peerIsMuted).updatedPeerDiscussionId(peerDiscussionId).updatedPeerGeoLocation(peerGeoLocation).updatedExplicitelyCanPinMessages(explicitelyCanPinMessages).updatedHasScheduledMessages(false).updatedCurrentSendAsPeerId(currentSendAsPeerId) }.updatedIsNotAccessible(isNotAccessible).updatedContactStatus(contactStatus).updatedHasBots(hasBots).updatedIsArchived(isArchived).updatedPeerIsMuted(peerIsMuted).updatedPeerDiscussionId(peerDiscussionId).updatedPeerGeoLocation(peerGeoLocation).updatedExplicitelyCanPinMessages(explicitelyCanPinMessages).updatedHasScheduledMessages(false).updatedCurrentSendAsPeerId(currentSendAsPeerId)
.updatedCopyProtectionEnabled(copyProtectionEnabled)
}) })
if !strongSelf.didSetChatLocationInfoReady { if !strongSelf.didSetChatLocationInfoReady {
strongSelf.didSetChatLocationInfoReady = true strongSelf.didSetChatLocationInfoReady = true
@ -8715,7 +8718,7 @@ public final class ChatControllerImpl: TelegramBaseController, ChatController, G
interfaceState = interfaceState.withUpdatedHistoryScrollState(scrollState) interfaceState = interfaceState.withUpdatedHistoryScrollState(scrollState)
} }
interfaceState = interfaceState.withUpdatedInputLanguage(self.chatDisplayNode.currentTextInputLanguage) interfaceState = interfaceState.withUpdatedInputLanguage(self.chatDisplayNode.currentTextInputLanguage)
if interfaceState.composeInputState.inputText.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { if interfaceState.composeInputState.inputText.string.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && interfaceState.replyMessageId == nil {
interfaceState = interfaceState.withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: ""))) interfaceState = interfaceState.withUpdatedComposeInputState(ChatTextInputState(inputText: NSAttributedString(string: "")))
} }
let _ = ChatInterfaceState.update(engine: self.context.engine, peerId: peerId, threadId: threadId, { _ in let _ = ChatInterfaceState.update(engine: self.context.engine, peerId: peerId, threadId: threadId, { _ in

View File

@ -277,6 +277,12 @@ class ChatControllerNode: ASDisplayNode, UIScrollViewDelegate {
if attribute is ViewCountMessageAttribute{ if attribute is ViewCountMessageAttribute{
return false return false
} }
if attribute is ForwardCountMessageAttribute {
return false
}
if attribute is ReactionsMessageAttribute {
return false
}
return true return true
}) })

View File

@ -17,6 +17,7 @@ import UniversalMediaPlayer
import TelegramUniversalVideoContent import TelegramUniversalVideoContent
import GalleryUI import GalleryUI
import WallpaperBackgroundNode import WallpaperBackgroundNode
import InvisibleInkDustNode
private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId) -> NSAttributedString? { private func attributedServiceMessageString(theme: ChatPresentationThemeData, strings: PresentationStrings, nameDisplayOrder: PresentationPersonNameOrder, dateTimeFormat: PresentationDateTimeFormat, message: Message, accountPeerId: PeerId) -> NSAttributedString? {
return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: false) return universalServiceMessageString(presentationData: (theme.theme, theme.wallpaper), strings: strings, nameDisplayOrder: nameDisplayOrder, dateTimeFormat: dateTimeFormat, message: EngineMessage(message), accountPeerId: accountPeerId, forChatList: false)
@ -24,6 +25,7 @@ private func attributedServiceMessageString(theme: ChatPresentationThemeData, st
class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode { class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
let labelNode: TextNode let labelNode: TextNode
private var dustNode: InvisibleInkDustNode?
var backgroundNode: WallpaperBubbleBackgroundNode? var backgroundNode: WallpaperBubbleBackgroundNode?
var backgroundColorNode: ASDisplayNode var backgroundColorNode: ASDisplayNode
let backgroundMaskNode: ASImageNode let backgroundMaskNode: ASImageNode
@ -277,6 +279,25 @@ class ChatMessageActionBubbleContentNode: ChatMessageBubbleContentNode {
strongSelf.labelNode.frame = labelFrame strongSelf.labelNode.frame = labelFrame
strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper) strongSelf.backgroundColorNode.backgroundColor = selectDateFillStaticColor(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper)
if !labelLayout.spoilers.isEmpty {
let dustColor = serviceMessageColorComponents(theme: item.presentationData.theme.theme, wallpaper: item.presentationData.theme.wallpaper).primaryText
let dustNode: InvisibleInkDustNode
if let current = strongSelf.dustNode {
dustNode = current
} else {
dustNode = InvisibleInkDustNode(textNode: nil)
dustNode.isUserInteractionEnabled = false
strongSelf.dustNode = dustNode
strongSelf.insertSubnode(dustNode, aboveSubnode: strongSelf.labelNode)
}
dustNode.frame = labelFrame.insetBy(dx: -3.0, dy: -3.0).offsetBy(dx: 0.0, dy: 1.0)
dustNode.update(size: dustNode.frame.size, color: dustColor, textColor: dustColor, rects: labelLayout.spoilers.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) }, wordRects: labelLayout.spoilerWords.map { $0.1.offsetBy(dx: 3.0, dy: 3.0).insetBy(dx: 1.0, dy: 1.0) })
} else if let dustNode = strongSelf.dustNode {
dustNode.removeFromSupernode()
strongSelf.dustNode = nil
}
let baseBackgroundFrame = labelFrame.offsetBy(dx: 0.0, dy: -11.0) let baseBackgroundFrame = labelFrame.offsetBy(dx: 0.0, dy: -11.0)
if let (offset, image) = backgroundMaskImage { if let (offset, image) = backgroundMaskImage {

View File

@ -206,7 +206,7 @@ final class ChatMessageAccessibilityData {
if let chatPeer = message.peers[item.message.id.peerId] { if let chatPeer = message.peers[item.message.id.peerId] {
let authorName = message.author.flatMap(EnginePeer.init)?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder) let authorName = message.author.flatMap(EnginePeer.init)?.displayTitle(strings: item.presentationData.strings, displayOrder: item.presentationData.nameDisplayOrder)
let (_, _, messageText) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: [EngineMessage(message)], chatPeer: EngineRenderedPeer(peer: EnginePeer(chatPeer)), accountPeerId: item.context.account.peerId) let (_, _, messageText, _) = chatListItemStrings(strings: item.presentationData.strings, nameDisplayOrder: item.presentationData.nameDisplayOrder, dateTimeFormat: item.presentationData.dateTimeFormat, messages: [EngineMessage(message)], chatPeer: EngineRenderedPeer(peer: EnginePeer(chatPeer)), accountPeerId: item.context.account.peerId)
var text = messageText var text = messageText

View File

@ -876,6 +876,7 @@ class ChatMessagePollBubbleContentNode: ChatMessageBubbleContentNode {
self.votersNode.contentMode = .topLeft self.votersNode.contentMode = .topLeft
self.votersNode.contentsScale = UIScreenScale self.votersNode.contentsScale = UIScreenScale
self.votersNode.displaysAsynchronously = false self.votersNode.displaysAsynchronously = false
self.votersNode.clipsToBounds = true
var displaySolution: (() -> Void)? var displaySolution: (() -> Void)?
self.solutionButtonNode = SolutionButtonNode(pressed: { self.solutionButtonNode = SolutionButtonNode(pressed: {

View File

@ -106,7 +106,7 @@ class ChatMessageReplyInfoNode: ASDisplayNode {
} }
} }
if entities.count > 0 { if entities.count > 0 {
messageText = stringWithAppliedEntities(message.text, entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false)
} else { } else {
messageText = NSAttributedString(string: textString, font: textFont, textColor: textColor) messageText = NSAttributedString(string: textString, font: textFont, textColor: textColor)
} }

View File

@ -468,7 +468,7 @@ final class ChatPinnedMessageTitlePanelNode: ChatTitleAccessoryPanelNode {
} }
let textColor = theme.chat.inputPanel.primaryTextColor let textColor = theme.chat.inputPanel.primaryTextColor
if entities.count > 0 { if entities.count > 0 {
messageText = stringWithAppliedEntities(message.text, entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false)
} else { } else {
messageText = NSAttributedString(string: foldLineBreaks(textString), font: textFont, textColor: textColor) messageText = NSAttributedString(string: foldLineBreaks(textString), font: textFont, textColor: textColor)
} }

View File

@ -1597,9 +1597,9 @@ private class QrContentNode: ASDisplayNode, ContentNode {
self.codeTextNode.attributedText = NSAttributedString(string: self.codeTextNode.attributedText?.string ?? "", font: Font.with(size: fontSize, design: .round, weight: .bold, traits: []), textColor: .black) self.codeTextNode.attributedText = NSAttributedString(string: self.codeTextNode.attributedText?.string ?? "", font: Font.with(size: fontSize, design: .round, weight: .bold, traits: []), textColor: .black)
let codeBackgroundWidth = size.width - codeInset * 2.0 let codeBackgroundWidth = min(300.0, size.width - codeInset * 2.0)
let codeBackgroundHeight = floor(codeBackgroundWidth * 1.1) let codeBackgroundHeight = floor(codeBackgroundWidth * 1.1)
let codeBackgroundFrame = CGRect(x: codeInset, y: topInset + floor((size.height - bottomInset - codeBackgroundHeight) / 2.0), width: codeBackgroundWidth, height: codeBackgroundHeight) let codeBackgroundFrame = CGRect(x: floor((size.width - codeBackgroundWidth) / 2.0), y: topInset + floor((size.height - bottomInset - codeBackgroundHeight) / 2.0), width: codeBackgroundWidth, height: codeBackgroundHeight)
transition.updateFrame(node: self.codeBackgroundNode, frame: codeBackgroundFrame) transition.updateFrame(node: self.codeBackgroundNode, frame: codeBackgroundFrame)
transition.updateFrame(node: self.codeForegroundNode, frame: codeBackgroundFrame) transition.updateFrame(node: self.codeForegroundNode, frame: codeBackgroundFrame)
transition.updateFrame(node: self.codeMaskNode, frame: CGRect(origin: CGPoint(), size: codeBackgroundFrame.size)) transition.updateFrame(node: self.codeMaskNode, frame: CGRect(origin: CGPoint(), size: codeBackgroundFrame.size))

View File

@ -49,6 +49,9 @@ private func chatInputStateString(attributedString: NSAttributedString) -> NSAtt
string.addAttribute(ChatTextInputAttributes.monospace, value: true as NSNumber, range: range) string.addAttribute(ChatTextInputAttributes.monospace, value: true as NSNumber, range: range)
} }
} }
if let value = attributes[.backgroundColor] as? UIColor, value.rgb == UIColor.gray.rgb {
string.addAttribute(ChatTextInputAttributes.spoiler, value: true as NSNumber, range: range)
}
if let _ = attributes[.strikethroughStyle] { if let _ = attributes[.strikethroughStyle] {
string.addAttribute(ChatTextInputAttributes.strikethrough, value: true as NSNumber, range: range) string.addAttribute(ChatTextInputAttributes.strikethrough, value: true as NSNumber, range: range)
} }

View File

@ -135,7 +135,7 @@ final class ReplyAccessoryPanelNode: AccessoryPanelNode {
} }
let textColor = strongSelf.theme.chat.inputPanel.primaryTextColor let textColor = strongSelf.theme.chat.inputPanel.primaryTextColor
if entities.count > 0 { if entities.count > 0 {
messageText = stringWithAppliedEntities(message.text, entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false) messageText = stringWithAppliedEntities(trimToLineCount(message.text, lineCount: 1), entities: entities, baseColor: textColor, linkColor: textColor, baseFont: textFont, linkFont: textFont, boldFont: textFont, italicFont: textFont, boldItalicFont: textFont, fixedFont: textFont, blockQuoteFont: textFont, underlineLinks: false)
} else { } else {
messageText = NSAttributedString(string: text, font: textFont, textColor: isMedia ? strongSelf.theme.chat.inputPanel.secondaryTextColor : strongSelf.theme.chat.inputPanel.primaryTextColor) messageText = NSAttributedString(string: text, font: textFont, textColor: isMedia ? strongSelf.theme.chat.inputPanel.secondaryTextColor : strongSelf.theme.chat.inputPanel.primaryTextColor)
} }

View File

@ -69,7 +69,9 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
if nsString == nil { if nsString == nil {
nsString = text as NSString nsString = text as NSString
} }
if range.location + range.length > stringLength { if range.location > stringLength {
continue
} else if range.location + range.length > stringLength {
range.location = max(0, stringLength - range.length) range.location = max(0, stringLength - range.length)
range.length = stringLength - range.location range.length = stringLength - range.location
} }
@ -226,7 +228,11 @@ public func stringWithAppliedEntities(_ text: String, entities: [MessageTextEnti
} }
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.BankCard), value: nsString!.substring(with: range), range: range) string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.BankCard), value: nsString!.substring(with: range), range: range)
case .Spoiler: case .Spoiler:
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler), value: true as NSNumber, range: range) if external {
string.addAttribute(NSAttributedString.Key.backgroundColor, value: UIColor.gray, range: range)
} else {
string.addAttribute(NSAttributedString.Key(rawValue: TelegramTextAttributes.Spoiler), value: true as NSNumber, range: range)
}
case let .Custom(type): case let .Custom(type):
if type == ApplicationSpecificEntityType.Timecode { if type == ApplicationSpecificEntityType.Timecode {
string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: range) string.addAttribute(NSAttributedString.Key.foregroundColor, value: linkColor, range: range)

View File

@ -11,11 +11,12 @@ private final class LinkHelperClass: NSObject {
public var supportedTranslationLanguages = [ public var supportedTranslationLanguages = [
"en", "en",
"ar", "ar",
"zh", "zh-Hans",
"zh-Hant",
"fr", "fr",
"de", "de",
"it", "it",
"jp", "ja",
"ko", "ko",
"pt", "pt",
"ru", "ru",